summaryrefslogtreecommitdiffstats
path: root/sfx2/source/bastyp
diff options
context:
space:
mode:
Diffstat (limited to 'sfx2/source/bastyp')
-rw-r--r--sfx2/source/bastyp/bitset.cxx108
-rw-r--r--sfx2/source/bastyp/fltfnc.cxx1111
-rw-r--r--sfx2/source/bastyp/fltlst.cxx118
-rw-r--r--sfx2/source/bastyp/fltlst.hxx50
-rw-r--r--sfx2/source/bastyp/frmhtml.cxx101
-rw-r--r--sfx2/source/bastyp/frmhtmlw.cxx294
-rw-r--r--sfx2/source/bastyp/helper.cxx229
-rw-r--r--sfx2/source/bastyp/mieclip.cxx103
-rw-r--r--sfx2/source/bastyp/progress.cxx401
-rw-r--r--sfx2/source/bastyp/sfxhtml.cxx345
-rw-r--r--sfx2/source/bastyp/sfxresid.cxx24
11 files changed, 2884 insertions, 0 deletions
diff --git a/sfx2/source/bastyp/bitset.cxx b/sfx2/source/bastyp/bitset.cxx
new file mode 100644
index 000000000..b6980a890
--- /dev/null
+++ b/sfx2/source/bastyp/bitset.cxx
@@ -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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/log.hxx>
+#include <sal/types.h>
+
+#include <bitset.hxx>
+
+#include <string.h>
+
+// creates the asymmetric difference with another bitset
+
+IndexBitSet& IndexBitSet::operator-=(sal_uInt16 nBit)
+{
+ sal_uInt16 nBlock = nBit / 32;
+ sal_uInt32 nBitVal = 1U << (nBit % 32);
+
+ if ( nBlock >= nBlocks )
+ return *this;
+
+ if ( pBitmap[nBlock] & nBitVal )
+ {
+ pBitmap[nBlock] &= ~nBitVal;
+ }
+
+ return *this;
+}
+
+// unify with a single bit
+
+IndexBitSet& IndexBitSet::operator|=( sal_uInt16 nBit )
+{
+ sal_uInt16 nBlock = nBit / 32;
+ sal_uInt32 nBitVal = 1U << (nBit % 32);
+
+ if ( nBlock >= nBlocks )
+ {
+ sal_uInt32 *pNewMap = new sal_uInt32[nBlock+1];
+ memset( pNewMap + nBlocks, 0, 4 * (nBlock - nBlocks + 1) );
+
+ if ( pBitmap )
+ {
+ memcpy( pNewMap, pBitmap.get(), 4 * nBlocks );
+ }
+ pBitmap.reset(pNewMap);
+ nBlocks = nBlock+1;
+ }
+
+ if ( (pBitmap[nBlock] & nBitVal) == 0 )
+ {
+ pBitmap[nBlock] |= nBitVal;
+ }
+
+ return *this;
+}
+
+
+// determines if the bit is set (may be the only one)
+
+bool IndexBitSet::Contains( sal_uInt16 nBit ) const
+{
+ sal_uInt16 nBlock = nBit / 32;
+ sal_uInt32 nBitVal = 1U << (nBit % 32);
+
+ if ( nBlock >= nBlocks )
+ return false;
+ return ( nBitVal & pBitmap[nBlock] ) == nBitVal;
+}
+
+IndexBitSet::IndexBitSet()
+{
+ nBlocks = 0;
+}
+
+IndexBitSet::~IndexBitSet()
+{
+}
+
+sal_uInt16 IndexBitSet::GetFreeIndex()
+{
+ for(sal_uInt16 i=0;i<SAL_MAX_UINT16;i++)
+ if(!Contains(i))
+ {
+ *this|=i;
+ return i;
+ }
+ SAL_WARN( "sfx", "IndexBitSet contains more than SAL_MAX_UINT16 entries");
+ return 0;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sfx2/source/bastyp/fltfnc.cxx b/sfx2/source/bastyp/fltfnc.cxx
new file mode 100644
index 000000000..56638fc1c
--- /dev/null
+++ b/sfx2/source/bastyp/fltfnc.cxx
@@ -0,0 +1,1111 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <com/sun/star/uno/Exception.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/container/XEnumeration.hpp>
+#include <com/sun/star/document/XTypeDetection.hpp>
+#include <com/sun/star/container/XContainerQuery.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/task/XInteractionHandler.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+
+#include <comphelper/sequenceashashmap.hxx>
+
+#include <sot/exchange.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+#include <svl/stritem.hxx>
+
+#include <comphelper/processfactory.hxx>
+
+#include <sal/types.h>
+#include <com/sun/star/uno/Reference.hxx>
+#include <unotools/moduleoptions.hxx>
+#include <unotools/mediadescriptor.hxx>
+#include <tools/urlobj.hxx>
+
+#include <unotools/syslocale.hxx>
+#include <unotools/charclass.hxx>
+
+#include <sfx2/docfilt.hxx>
+#include <sfx2/fcontnr.hxx>
+#include <sfxtypes.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/strings.hrc>
+#include <sfx2/sfxresid.hxx>
+#include <sfx2/objsh.hxx>
+#include <sfx2/sfxsids.hrc>
+#include "fltlst.hxx"
+#include <arrdecl.hxx>
+
+#include <vector>
+#include <memory>
+
+#if defined(DBG_UTIL)
+unsigned SfxStack::nLevel = 0;
+#endif
+
+using namespace com::sun::star;
+
+static SfxFilterList_Impl* pFilterArr = nullptr;
+static bool bFirstRead = true;
+
+static void CreateFilterArr()
+{
+ static SfxFilterList_Impl theSfxFilterArray;
+ pFilterArr = &theSfxFilterArray;
+ static SfxFilterListener theSfxFilterListener;
+}
+
+static OUString ToUpper_Impl( const OUString &rStr )
+{
+ return SvtSysLocale().GetCharClass().uppercase( rStr );
+}
+
+class SfxFilterContainer_Impl
+{
+public:
+ OUString aName;
+
+ explicit SfxFilterContainer_Impl( const OUString& rName )
+ : aName( rName )
+ {
+ }
+};
+
+std::shared_ptr<const SfxFilter> SfxFilterContainer::GetFilter4EA(const OUString& rEA, SfxFilterFlags nMust, SfxFilterFlags nDont) const
+{
+ SfxFilterMatcher aMatch(pImpl->aName);
+ return aMatch.GetFilter4EA(rEA, nMust, nDont);
+}
+
+std::shared_ptr<const SfxFilter> SfxFilterContainer::GetFilter4Extension(const OUString& rExt, SfxFilterFlags nMust, SfxFilterFlags nDont) const
+{
+ SfxFilterMatcher aMatch(pImpl->aName);
+ return aMatch.GetFilter4Extension(rExt, nMust, nDont);
+}
+
+std::shared_ptr<const SfxFilter> SfxFilterContainer::GetFilter4FilterName(const OUString& rName, SfxFilterFlags nMust, SfxFilterFlags nDont) const
+{
+ SfxFilterMatcher aMatch(pImpl->aName);
+ return aMatch.GetFilter4FilterName(rName, nMust, nDont);
+}
+
+std::shared_ptr<const SfxFilter> SfxFilterContainer::GetAnyFilter( SfxFilterFlags nMust, SfxFilterFlags nDont ) const
+{
+ SfxFilterMatcher aMatch( pImpl->aName );
+ return aMatch.GetAnyFilter( nMust, nDont );
+}
+
+
+SfxFilterContainer::SfxFilterContainer( const OUString& rName )
+ : pImpl( new SfxFilterContainer_Impl( rName ) )
+{
+}
+
+
+SfxFilterContainer::~SfxFilterContainer()
+{
+}
+
+
+OUString const & SfxFilterContainer::GetName() const
+{
+ return pImpl->aName;
+}
+
+std::shared_ptr<const SfxFilter> SfxFilterContainer::GetDefaultFilter_Impl( std::u16string_view rName )
+{
+ // Try to find out the type of factory.
+ // Interpret given name as Service- and ShortName!
+ SvtModuleOptions aOpt;
+ SvtModuleOptions::EFactory eFactory = SvtModuleOptions::ClassifyFactoryByServiceName(rName);
+ if (eFactory == SvtModuleOptions::EFactory::UNKNOWN_FACTORY)
+ eFactory = SvtModuleOptions::ClassifyFactoryByShortName(rName);
+
+ // could not classify factory by its service nor by its short name.
+ // Must be an unknown factory! => return NULL
+ if (eFactory == SvtModuleOptions::EFactory::UNKNOWN_FACTORY)
+ return nullptr;
+
+ // For the following code we need some additional information.
+ OUString sServiceName = aOpt.GetFactoryName(eFactory);
+ OUString sDefaultFilter = aOpt.GetFactoryDefaultFilter(eFactory);
+
+ // Try to get the default filter. Don't forget to verify it.
+ // May the set default filter does not exists any longer or
+ // does not fit the given factory.
+ const SfxFilterMatcher aMatcher;
+ std::shared_ptr<const SfxFilter> pFilter = aMatcher.GetFilter4FilterName(sDefaultFilter);
+
+ if (
+ pFilter &&
+ !pFilter->GetServiceName().equalsIgnoreAsciiCase(sServiceName)
+ )
+ {
+ pFilter = nullptr;
+ }
+
+ // If at least no default filter could be located - use any filter of this
+ // factory.
+ if (!pFilter)
+ {
+ if ( bFirstRead )
+ ReadFilters_Impl();
+
+ for (const std::shared_ptr<const SfxFilter>& pCheckFilter : *pFilterArr)
+ {
+ if ( pCheckFilter->GetServiceName().equalsIgnoreAsciiCase(sServiceName) )
+ {
+ pFilter = pCheckFilter;
+ break;
+ }
+ }
+ }
+
+ return pFilter;
+}
+
+
+// Impl-Data is shared between all FilterMatchers of the same factory
+class SfxFilterMatcher_Impl
+{
+public:
+ OUString aName;
+ mutable SfxFilterList_Impl* pList; // is created on demand
+
+ void InitForIterating() const;
+ void Update() const;
+ explicit SfxFilterMatcher_Impl(const OUString &rName)
+ : aName(rName)
+ , pList(nullptr)
+ {
+ }
+ ~SfxFilterMatcher_Impl()
+ {
+ // SfxFilterMatcher_Impl::InitForIterating() will set pList to
+ // either the global filter array matcher pFilterArr, or to
+ // a new SfxFilterList_Impl.
+ if (pList != pFilterArr)
+ delete pList;
+ }
+};
+
+namespace
+{
+ std::vector<std::unique_ptr<SfxFilterMatcher_Impl> > aImplArr;
+ int nSfxFilterMatcherCount;
+
+ SfxFilterMatcher_Impl & getSfxFilterMatcher_Impl(const OUString &rName)
+ {
+ OUString aName;
+
+ if (!rName.isEmpty())
+ aName = SfxObjectShell::GetServiceNameFromFactory(rName);
+
+ // find the impl-Data of any comparable FilterMatcher that was created
+ // previously
+ for (std::unique_ptr<SfxFilterMatcher_Impl>& aImpl : aImplArr)
+ if (aImpl->aName == aName)
+ return *aImpl;
+
+ // first Matcher created for this factory
+ aImplArr.push_back(std::make_unique<SfxFilterMatcher_Impl>(aName));
+ return *aImplArr.back();
+ }
+}
+
+SfxFilterMatcher::SfxFilterMatcher( const OUString& rName )
+ : m_rImpl( getSfxFilterMatcher_Impl(rName) )
+{
+ ++nSfxFilterMatcherCount;
+}
+
+SfxFilterMatcher::SfxFilterMatcher()
+ : m_rImpl( getSfxFilterMatcher_Impl(OUString()) )
+{
+ // global FilterMatcher always uses global filter array (also created on
+ // demand)
+ ++nSfxFilterMatcherCount;
+}
+
+SfxFilterMatcher::~SfxFilterMatcher()
+{
+ --nSfxFilterMatcherCount;
+ if (nSfxFilterMatcherCount == 0)
+ aImplArr.clear();
+}
+
+void SfxFilterMatcher_Impl::Update() const
+{
+ if ( pList )
+ {
+ // this List was already used
+ pList->clear();
+ for (const std::shared_ptr<const SfxFilter>& pFilter : *pFilterArr)
+ {
+ if ( pFilter->GetServiceName() == aName )
+ pList->push_back( pFilter );
+ }
+ }
+}
+
+void SfxFilterMatcher_Impl::InitForIterating() const
+{
+ if ( pList )
+ return;
+
+ if ( bFirstRead )
+ // global filter array has not been created yet
+ SfxFilterContainer::ReadFilters_Impl();
+
+ if ( !aName.isEmpty() )
+ {
+ // matcher of factory: use only filters of that document type
+ pList = new SfxFilterList_Impl;
+ Update();
+ }
+ else
+ {
+ // global matcher: use global filter array
+ pList = pFilterArr;
+ }
+}
+
+std::shared_ptr<const SfxFilter> SfxFilterMatcher::GetAnyFilter( SfxFilterFlags nMust, SfxFilterFlags nDont ) const
+{
+ m_rImpl.InitForIterating();
+ for (const std::shared_ptr<const SfxFilter>& pFilter : *m_rImpl.pList)
+ {
+ SfxFilterFlags nFlags = pFilter->GetFilterFlags();
+ if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) )
+ return pFilter;
+ }
+
+ return nullptr;
+}
+
+
+ErrCode SfxFilterMatcher::GuessFilterIgnoringContent(
+ SfxMedium const & rMedium,
+ std::shared_ptr<const SfxFilter>& rpFilter ) const
+{
+ uno::Reference<document::XTypeDetection> xDetection(
+ comphelper::getProcessServiceFactory()->createInstance("com.sun.star.document.TypeDetection"), uno::UNO_QUERY);
+
+ OUString sTypeName;
+ try
+ {
+ sTypeName = xDetection->queryTypeByURL( rMedium.GetURLObject().GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
+ }
+ catch (uno::Exception&)
+ {
+ }
+
+ rpFilter = nullptr;
+ if ( !sTypeName.isEmpty() )
+ {
+ // make sure filter list is initialized
+ m_rImpl.InitForIterating();
+ rpFilter = GetFilter4EA( sTypeName );
+ }
+
+ return rpFilter ? ERRCODE_NONE : ERRCODE_ABORT;
+}
+
+
+ErrCode SfxFilterMatcher::GuessFilter( SfxMedium& rMedium, std::shared_ptr<const SfxFilter>& rpFilter, SfxFilterFlags nMust, SfxFilterFlags nDont ) const
+{
+ return GuessFilterControlDefaultUI( rMedium, rpFilter, nMust, nDont );
+}
+
+
+ErrCode SfxFilterMatcher::GuessFilterControlDefaultUI( SfxMedium& rMedium, std::shared_ptr<const SfxFilter>& rpFilter, SfxFilterFlags nMust, SfxFilterFlags nDont ) const
+{
+ std::shared_ptr<const SfxFilter> pOldFilter = rpFilter;
+
+ // no detection service -> nothing to do !
+ uno::Reference<document::XTypeDetection> xDetection(
+ comphelper::getProcessServiceFactory()->createInstance("com.sun.star.document.TypeDetection"), uno::UNO_QUERY);
+
+ if (!xDetection.is())
+ return ERRCODE_ABORT;
+
+ try
+ {
+ // open the stream one times only ...
+ // Otherwise it will be tried more than once and show the same interaction more than once ...
+
+ OUString sURL( rMedium.GetURLObject().GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
+ uno::Reference< io::XInputStream > xInStream = rMedium.GetInputStream();
+ OUString aFilterName;
+ OUString sTypeName;
+
+ // stream exists => deep detection (with preselection ... if possible)
+ if (xInStream.is())
+ {
+ utl::MediaDescriptor aDescriptor;
+
+ aDescriptor[utl::MediaDescriptor::PROP_URL ] <<= sURL;
+ aDescriptor[utl::MediaDescriptor::PROP_INPUTSTREAM ] <<= xInStream;
+ aDescriptor[utl::MediaDescriptor::PROP_INTERACTIONHANDLER] <<= rMedium.GetInteractionHandler();
+ SfxStringItem const * it = static_cast<SfxStringItem const *>(
+ rMedium.GetItemSet()->GetItem(SID_REFERER));
+ if (it != nullptr) {
+ aDescriptor[utl::MediaDescriptor::PROP_REFERRER]
+ <<= it->GetValue();
+ }
+
+ if ( !m_rImpl.aName.isEmpty() )
+ aDescriptor[utl::MediaDescriptor::PROP_DOCUMENTSERVICE] <<= m_rImpl.aName;
+
+ if ( pOldFilter )
+ {
+ aDescriptor[utl::MediaDescriptor::PROP_TYPENAME ] <<= pOldFilter->GetTypeName();
+ aDescriptor[utl::MediaDescriptor::PROP_FILTERNAME] <<= pOldFilter->GetFilterName();
+ }
+
+ uno::Sequence< beans::PropertyValue > lDescriptor = aDescriptor.getAsConstPropertyValueList();
+ sTypeName = xDetection->queryTypeByDescriptor(lDescriptor, true); // lDescriptor is used as In/Out param ... don't use aDescriptor.getAsConstPropertyValueList() directly!
+
+ for (const auto& rProp : std::as_const(lDescriptor))
+ {
+ if (rProp.Name == "FilterName")
+ // Type detection picked a preferred filter for this format.
+ aFilterName = rProp.Value.get<OUString>();
+ }
+ }
+ // no stream exists => try flat detection without preselection as fallback
+ else
+ sTypeName = xDetection->queryTypeByURL(sURL);
+
+ if (!sTypeName.isEmpty())
+ {
+ std::shared_ptr<const SfxFilter> pNewFilter;
+ if (!aFilterName.isEmpty())
+ // Type detection returned a suitable filter for this. Use it.
+ pNewFilter = SfxFilter::GetFilterByName(aFilterName);
+
+ // fdo#78742 respect requested document service if set
+ if (!pNewFilter || (!m_rImpl.aName.isEmpty()
+ && m_rImpl.aName != pNewFilter->GetServiceName()))
+ {
+ // detect filter by given type
+ // In case of this matcher is bound to a particular document type:
+ // If there is no acceptable type for this document at all, the type detection has possibly returned something else.
+ // The DocumentService property is only a preselection, and all preselections are considered as optional!
+ // This "wrong" type will be sorted out now because we match only allowed filters to the detected type
+ uno::Sequence< beans::NamedValue > lQuery { { "Name", css::uno::Any(sTypeName) } };
+
+ pNewFilter = GetFilterForProps(lQuery, nMust, nDont);
+ }
+
+ if (pNewFilter)
+ {
+ rpFilter = pNewFilter;
+ return ERRCODE_NONE;
+ }
+ }
+ }
+ catch (const uno::Exception&)
+ {}
+
+ return ERRCODE_ABORT;
+}
+
+
+bool SfxFilterMatcher::IsFilterInstalled_Impl( const std::shared_ptr<const SfxFilter>& pFilter )
+{
+ if ( pFilter->GetFilterFlags() & SfxFilterFlags::MUSTINSTALL )
+ {
+ // Here could a re-installation be offered
+ OUString aText( SfxResId(STR_FILTER_NOT_INSTALLED) );
+ aText = aText.replaceFirst( "$(FILTER)", pFilter->GetUIName() );
+ std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(nullptr,
+ VclMessageType::Question, VclButtonsType::YesNo,
+ aText));
+ xQueryBox->set_default_response(RET_YES);
+
+ short nRet = xQueryBox->run();
+ if ( nRet == RET_YES )
+ {
+#ifdef DBG_UTIL
+ // Start Setup
+ std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(nullptr,
+ VclMessageType::Info, VclButtonsType::Ok,
+ "Here should the Setup now be starting!"));
+ xInfoBox->run();
+#endif
+ // Installation must still give feedback if it worked or not,
+ // then the Filterflag be deleted
+ }
+
+ return ( !(pFilter->GetFilterFlags() & SfxFilterFlags::MUSTINSTALL) );
+ }
+ else if ( pFilter->GetFilterFlags() & SfxFilterFlags::CONSULTSERVICE )
+ {
+ OUString aText( SfxResId(STR_FILTER_CONSULT_SERVICE) );
+ aText = aText.replaceFirst( "$(FILTER)", pFilter->GetUIName() );
+ std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(nullptr,
+ VclMessageType::Info, VclButtonsType::Ok,
+ aText));
+ xInfoBox->run();
+ return false;
+ }
+ else
+ return true;
+}
+
+
+ErrCode SfxFilterMatcher::DetectFilter( SfxMedium& rMedium, std::shared_ptr<const SfxFilter>& rpFilter ) const
+/* [Description]
+
+ Here the Filter selection box is pulled up. Otherwise GuessFilter
+ */
+
+{
+ std::shared_ptr<const SfxFilter> pOldFilter = rMedium.GetFilter();
+ if ( pOldFilter )
+ {
+ if( !IsFilterInstalled_Impl( pOldFilter ) )
+ pOldFilter = nullptr;
+ else
+ {
+ const SfxStringItem* pSalvageItem = SfxItemSet::GetItem<SfxStringItem>(rMedium.GetItemSet(), SID_DOC_SALVAGE, false);
+ if ( ( pOldFilter->GetFilterFlags() & SfxFilterFlags::PACKED ) && pSalvageItem )
+ // Salvage is always done without packing
+ pOldFilter = nullptr;
+ }
+ }
+
+ std::shared_ptr<const SfxFilter> pFilter = pOldFilter;
+
+ bool bPreview = rMedium.IsPreview_Impl();
+ const SfxStringItem* pReferer = SfxItemSet::GetItem<SfxStringItem>(rMedium.GetItemSet(), SID_REFERER, false);
+ if ( bPreview && rMedium.IsRemote() && ( !pReferer || !pReferer->GetValue().match("private:searchfolder:") ) )
+ return ERRCODE_ABORT;
+
+ ErrCode nErr = GuessFilter( rMedium, pFilter );
+ if ( nErr == ERRCODE_ABORT )
+ return nErr;
+
+ if ( nErr == ERRCODE_IO_PENDING )
+ {
+ rpFilter = pFilter;
+ return nErr;
+ }
+
+ if ( !pFilter )
+ {
+ std::shared_ptr<const SfxFilter> pInstallFilter;
+
+ // Now test the filter which are not installed (ErrCode is irrelevant)
+ GuessFilter( rMedium, pInstallFilter, SfxFilterFlags::IMPORT, SfxFilterFlags::CONSULTSERVICE );
+ if ( pInstallFilter )
+ {
+ if ( IsFilterInstalled_Impl( pInstallFilter ) )
+ // Maybe the filter was installed afterwards.
+ pFilter = pInstallFilter;
+ }
+ else
+ {
+ // Now test the filter, which first must be obtained by Star
+ // (ErrCode is irrelevant)
+ GuessFilter( rMedium, pInstallFilter, SfxFilterFlags::IMPORT, SfxFilterFlags::NONE );
+ if ( pInstallFilter )
+ IsFilterInstalled_Impl( pInstallFilter );
+ }
+ }
+
+ bool bHidden = bPreview;
+ const SfxStringItem* pFlags = SfxItemSet::GetItem<SfxStringItem>(rMedium.GetItemSet(), SID_OPTIONS, false);
+ if ( !bHidden && pFlags )
+ {
+ OUString aFlags( pFlags->GetValue() );
+ aFlags = aFlags.toAsciiUpperCase();
+ if( -1 != aFlags.indexOf( 'H' ) )
+ bHidden = true;
+ }
+ rpFilter = pFilter;
+
+ if ( bHidden )
+ nErr = pFilter ? ERRCODE_NONE : ERRCODE_ABORT;
+ return nErr;
+}
+
+std::shared_ptr<const SfxFilter> SfxFilterMatcher::GetFilterForProps( const css::uno::Sequence < beans::NamedValue >& aSeq, SfxFilterFlags nMust, SfxFilterFlags nDont ) const
+{
+ uno::Reference< lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory();
+ if( !xServiceManager )
+ return nullptr;
+
+ static constexpr OUStringLiteral sTypeDetection = u"com.sun.star.document.TypeDetection";
+ uno::Reference< container::XContainerQuery > xTypeCFG( xServiceManager->createInstance( sTypeDetection ), uno::UNO_QUERY );
+ if ( !xTypeCFG )
+ return nullptr;
+
+ // make query for all types matching the properties
+ uno::Reference < css::container::XEnumeration > xEnum = xTypeCFG->createSubSetEnumerationByProperties( aSeq );
+ uno::Sequence<beans::PropertyValue> aProps;
+ while ( xEnum->hasMoreElements() )
+ {
+ static constexpr OUStringLiteral sPreferredFilter = u"PreferredFilter";
+ static constexpr OUStringLiteral sName = u"Name";
+
+ xEnum->nextElement() >>= aProps;
+ OUString aValue, aName;
+ for( const auto & rPropVal : aProps)
+ {
+ if (rPropVal.Name == sPreferredFilter)
+ rPropVal.Value >>= aValue;
+ else if (rPropVal.Name == sName)
+ rPropVal.Value >>= aName;
+ }
+
+ // try to get the preferred filter (works without loading all filters!)
+ if ( !aValue.isEmpty() )
+ {
+ std::shared_ptr<const SfxFilter> pFilter = SfxFilter::GetFilterByName( aValue );
+ if ( !pFilter || (pFilter->GetFilterFlags() & nMust) != nMust || (pFilter->GetFilterFlags() & nDont ) )
+ // check for filter flags
+ // pFilter == 0: if preferred filter is a Writer filter, but Writer module is not installed
+ continue;
+
+ if ( !m_rImpl.aName.isEmpty() )
+ {
+ // if this is not the global FilterMatcher: check if filter matches the document type
+ if ( pFilter->GetServiceName() != m_rImpl.aName )
+ {
+ // preferred filter belongs to another document type; now we must search the filter
+ m_rImpl.InitForIterating();
+ pFilter = GetFilter4EA( aName, nMust, nDont );
+ if ( pFilter )
+ return pFilter;
+ }
+ else
+ return pFilter;
+ }
+ else
+ return pFilter;
+ }
+ }
+
+ return nullptr;
+}
+
+std::shared_ptr<const SfxFilter> SfxFilterMatcher::GetFilter4Mime( const OUString& rMediaType, SfxFilterFlags nMust, SfxFilterFlags nDont ) const
+{
+ if ( m_rImpl.pList )
+ {
+ for (const std::shared_ptr<const SfxFilter>& pFilter : *m_rImpl.pList)
+ {
+ SfxFilterFlags nFlags = pFilter->GetFilterFlags();
+ if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) && pFilter->GetMimeType() == rMediaType )
+ return pFilter;
+ }
+
+ return nullptr;
+ }
+
+ css::uno::Sequence < css::beans::NamedValue > aSeq { { "MediaType", css::uno::Any(rMediaType) } };
+ return GetFilterForProps( aSeq, nMust, nDont );
+}
+
+std::shared_ptr<const SfxFilter> SfxFilterMatcher::GetFilter4EA( const OUString& rType, SfxFilterFlags nMust, SfxFilterFlags nDont ) const
+{
+ if ( m_rImpl.pList )
+ {
+ std::shared_ptr<const SfxFilter> pFirst;
+ for (const std::shared_ptr<const SfxFilter>& pFilter : *m_rImpl.pList)
+ {
+ SfxFilterFlags nFlags = pFilter->GetFilterFlags();
+ if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) && pFilter->GetTypeName() == rType )
+ {
+ if (nFlags & SfxFilterFlags::PREFERED)
+ return pFilter;
+ if (!pFirst)
+ pFirst = pFilter;
+ }
+ }
+ if (pFirst)
+ return pFirst;
+
+ return nullptr;
+ }
+
+ css::uno::Sequence < css::beans::NamedValue > aSeq { { "Name", css::uno::Any(rType) } };
+ return GetFilterForProps( aSeq, nMust, nDont );
+}
+
+std::shared_ptr<const SfxFilter> SfxFilterMatcher::GetFilter4Extension( const OUString& rExt, SfxFilterFlags nMust, SfxFilterFlags nDont ) const
+{
+ if ( m_rImpl.pList )
+ {
+ if (OUString sExt = ToUpper_Impl(rExt); !sExt.isEmpty())
+ {
+ if (sExt[0] != '.')
+ sExt = "." + sExt;
+
+ for (const std::shared_ptr<const SfxFilter>& pFilter : *m_rImpl.pList)
+ {
+ SfxFilterFlags nFlags = pFilter->GetFilterFlags();
+ if ((nFlags & nMust) == nMust && !(nFlags & nDont))
+ {
+ OUString sWildCard = ToUpper_Impl(pFilter->GetWildcard().getGlob());
+
+ WildCard aCheck(sWildCard, ';');
+ if (aCheck.Matches(sExt))
+ return pFilter;
+ }
+ }
+ }
+
+ return nullptr;
+ }
+
+ // Use extension without dot!
+ OUString sExt( rExt );
+ if ( sExt.startsWith(".") )
+ sExt = sExt.copy(1);
+
+ css::uno::Sequence < css::beans::NamedValue > aSeq
+ { { "Extensions", css::uno::Any(uno::Sequence < OUString > { sExt } ) } };
+ return GetFilterForProps( aSeq, nMust, nDont );
+}
+
+std::shared_ptr<const SfxFilter> SfxFilterMatcher::GetFilter4ClipBoardId( SotClipboardFormatId nId, SfxFilterFlags nMust, SfxFilterFlags nDont ) const
+{
+ if (nId == SotClipboardFormatId::NONE)
+ return nullptr;
+
+ css::uno::Sequence < css::beans::NamedValue > aSeq
+ { { "ClipboardFormat", css::uno::Any(SotExchange::GetFormatName( nId )) } };
+ return GetFilterForProps( aSeq, nMust, nDont );
+}
+
+std::shared_ptr<const SfxFilter> SfxFilterMatcher::GetFilter4UIName( std::u16string_view rName, SfxFilterFlags nMust, SfxFilterFlags nDont ) const
+{
+ m_rImpl.InitForIterating();
+ std::shared_ptr<const SfxFilter> pFirstFilter;
+ for (const std::shared_ptr<const SfxFilter>& pFilter : *m_rImpl.pList)
+ {
+ SfxFilterFlags nFlags = pFilter->GetFilterFlags();
+ if ( (nFlags & nMust) == nMust &&
+ !(nFlags & nDont ) && pFilter->GetUIName() == rName )
+ {
+ if ( pFilter->GetFilterFlags() & SfxFilterFlags::PREFERED )
+ return pFilter;
+ else if ( !pFirstFilter )
+ pFirstFilter = pFilter;
+ }
+ }
+ return pFirstFilter;
+}
+
+std::shared_ptr<const SfxFilter> SfxFilterMatcher::GetFilter4FilterName( const OUString& rName, SfxFilterFlags nMust, SfxFilterFlags nDont ) const
+{
+ std::u16string_view aName( rName );
+ sal_Int32 nIndex = rName.indexOf(": ");
+ if ( nIndex != -1 )
+ {
+ SAL_WARN( "sfx.bastyp", "Old filter name used!");
+ aName = rName.subView( nIndex + 2 );
+ }
+
+ if ( bFirstRead )
+ {
+ uno::Reference< lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory();
+ uno::Reference< container::XNameAccess > xFilterCFG ;
+ uno::Reference< container::XNameAccess > xTypeCFG ;
+ if( xServiceManager.is() )
+ {
+ static constexpr OUStringLiteral sFilterFactory = u"com.sun.star.document.FilterFactory";
+ static constexpr OUStringLiteral sTypeDetection = u"com.sun.star.document.TypeDetection";
+ xFilterCFG.set( xServiceManager->createInstance( sFilterFactory ), uno::UNO_QUERY );
+ xTypeCFG.set( xServiceManager->createInstance( sTypeDetection ), uno::UNO_QUERY );
+ }
+
+ if( xFilterCFG.is() && xTypeCFG.is() )
+ {
+ if ( !pFilterArr )
+ CreateFilterArr();
+ else
+ {
+ for (const std::shared_ptr<const SfxFilter>& pFilter : *pFilterArr)
+ {
+ SfxFilterFlags nFlags = pFilter->GetFilterFlags();
+ if ((nFlags & nMust) == nMust && !(nFlags & nDont) && pFilter->GetFilterName().equalsIgnoreAsciiCase(aName))
+ return pFilter;
+ }
+ }
+
+ SfxFilterContainer::ReadSingleFilter_Impl( rName, xTypeCFG, xFilterCFG, false );
+ }
+ }
+
+ SfxFilterList_Impl* pList = m_rImpl.pList;
+ if ( !pList )
+ pList = pFilterArr;
+
+ for (const std::shared_ptr<const SfxFilter>& pFilter : *pList)
+ {
+ SfxFilterFlags nFlags = pFilter->GetFilterFlags();
+ if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) && pFilter->GetFilterName().equalsIgnoreAsciiCase(aName))
+ return pFilter;
+ }
+
+ return nullptr;
+}
+
+IMPL_LINK( SfxFilterMatcher, MaybeFileHdl_Impl, OUString*, pString, bool )
+{
+ std::shared_ptr<const SfxFilter> pFilter = GetFilter4Extension( *pString );
+ return pFilter &&
+ !pFilter->GetWildcard().Matches(u"") &&
+ !pFilter->GetWildcard().Matches(u"*.*") &&
+ !pFilter->GetWildcard().Matches(u"*");
+}
+
+
+SfxFilterMatcherIter::SfxFilterMatcherIter(
+ const SfxFilterMatcher& rMatcher,
+ SfxFilterFlags nOrMaskP, SfxFilterFlags nAndMaskP )
+ : nOrMask( nOrMaskP ), nAndMask( nAndMaskP ),
+ nCurrent(0), m_rMatch(rMatcher.m_rImpl)
+{
+ if( nOrMask == static_cast<SfxFilterFlags>(0xffff) ) //Due to faulty build on s
+ nOrMask = SfxFilterFlags::NONE;
+ m_rMatch.InitForIterating();
+}
+
+
+std::shared_ptr<const SfxFilter> SfxFilterMatcherIter::Find_Impl()
+{
+ std::shared_ptr<const SfxFilter> pFilter;
+ while( nCurrent < m_rMatch.pList->size() )
+ {
+ pFilter = (*m_rMatch.pList)[nCurrent++];
+ SfxFilterFlags nFlags = pFilter->GetFilterFlags();
+ if( ((nFlags & nOrMask) == nOrMask ) && !(nFlags & nAndMask ) )
+ break;
+ pFilter = nullptr;
+ }
+
+ return pFilter;
+}
+
+std::shared_ptr<const SfxFilter> SfxFilterMatcherIter::First()
+{
+ nCurrent = 0;
+ return Find_Impl();
+}
+
+
+std::shared_ptr<const SfxFilter> SfxFilterMatcherIter::Next()
+{
+ return Find_Impl();
+}
+
+/*---------------------------------------------------------------
+ helper to build own formatted string from given stringlist by
+ using given separator
+ ---------------------------------------------------------------*/
+static OUString implc_convertStringlistToString( const uno::Sequence< OUString >& lList ,
+ sal_Unicode cSeparator,
+ std::u16string_view sPrefix )
+{
+ OUStringBuffer sString ( 1000 ) ;
+ sal_Int32 nCount = lList.getLength();
+ sal_Int32 nItem = 0 ;
+ for( nItem=0; nItem<nCount; ++nItem )
+ {
+ if( !sPrefix.empty() )
+ {
+ sString.append( sPrefix );
+ }
+ sString.append( lList[nItem] );
+ if( nItem+1<nCount )
+ {
+ sString.append( cSeparator );
+ }
+ }
+ return sString.makeStringAndClear();
+}
+
+
+void SfxFilterContainer::ReadSingleFilter_Impl(
+ const OUString& rName,
+ const uno::Reference< container::XNameAccess >& xTypeCFG,
+ const uno::Reference< container::XNameAccess >& xFilterCFG,
+ bool bUpdate
+ )
+{
+ OUString sFilterName( rName );
+ SfxFilterList_Impl& rList = *pFilterArr;
+ uno::Sequence< beans::PropertyValue > lFilterProperties;
+ uno::Any aResult;
+ try
+ {
+ aResult = xFilterCFG->getByName( sFilterName );
+ }
+ catch( container::NoSuchElementException& )
+ {
+ aResult = uno::Any();
+ }
+
+ if( !(aResult >>= lFilterProperties) )
+ return;
+
+ // collect information to add filter to container
+ // (attention: some information aren't available on filter directly ... you must search for corresponding type too!)
+ SfxFilterFlags nFlags = SfxFilterFlags::NONE;
+ SotClipboardFormatId nClipboardId = SotClipboardFormatId::NONE;
+ sal_Int32 nFormatVersion = 0 ;
+ OUString sMimeType ;
+ OUString sType ;
+ OUString sUIName ;
+ OUString sHumanName ;
+ OUString sDefaultTemplate ;
+ OUString sUserData ;
+ OUString sExtension ;
+ OUString sServiceName ;
+ bool bEnabled = true ;
+
+ // first get directly available properties
+ for( const auto& rFilterProperty : std::as_const(lFilterProperties) )
+ {
+ if ( rFilterProperty.Name == "FileFormatVersion" )
+ {
+ rFilterProperty.Value >>= nFormatVersion;
+ }
+ else if ( rFilterProperty.Name == "TemplateName" )
+ {
+ rFilterProperty.Value >>= sDefaultTemplate;
+ }
+ else if ( rFilterProperty.Name == "Flags" )
+ {
+ sal_Int32 nTmp(0);
+ rFilterProperty.Value >>= nTmp;
+ assert((nTmp & ~o3tl::typed_flags<SfxFilterFlags>::mask) == 0);
+ nFlags = static_cast<SfxFilterFlags>(nTmp);
+ }
+ else if ( rFilterProperty.Name == "UIName" )
+ {
+ rFilterProperty.Value >>= sUIName;
+ }
+ else if ( rFilterProperty.Name == "UserData" )
+ {
+ uno::Sequence< OUString > lUserData;
+ rFilterProperty.Value >>= lUserData;
+ sUserData = implc_convertStringlistToString( lUserData, ',', u"" );
+ }
+ else if ( rFilterProperty.Name == "DocumentService" )
+ {
+ rFilterProperty.Value >>= sServiceName;
+ }
+ else if (rFilterProperty.Name == "ExportExtension")
+ {
+ // Extension preferred by the filter. This takes precedence
+ // over those that are given in the file format type.
+ rFilterProperty.Value >>= sExtension;
+ sExtension = "*." + sExtension;
+ }
+ else if ( rFilterProperty.Name == "Type" )
+ {
+ rFilterProperty.Value >>= sType;
+ // Try to get filter .. but look for any exceptions!
+ // May be filter was deleted by another thread ...
+ try
+ {
+ aResult = xTypeCFG->getByName( sType );
+ }
+ catch (const container::NoSuchElementException&)
+ {
+ aResult = uno::Any();
+ }
+
+ uno::Sequence< beans::PropertyValue > lTypeProperties;
+ if( aResult >>= lTypeProperties )
+ {
+ // get indirect available properties then (types)
+ for( const auto& rTypeProperty : std::as_const(lTypeProperties) )
+ {
+ if ( rTypeProperty.Name == "ClipboardFormat" )
+ {
+ rTypeProperty.Value >>= sHumanName;
+ }
+ else if ( rTypeProperty.Name == "MediaType" )
+ {
+ rTypeProperty.Value >>= sMimeType;
+ }
+ else if ( rTypeProperty.Name == "Extensions" )
+ {
+ if (sExtension.isEmpty())
+ {
+ uno::Sequence< OUString > lExtensions;
+ rTypeProperty.Value >>= lExtensions;
+ sExtension = implc_convertStringlistToString( lExtensions, ';', u"*." );
+ }
+ }
+ }
+ }
+ }
+ else if ( rFilterProperty.Name == "Enabled" )
+ {
+ rFilterProperty.Value >>= bEnabled;
+ }
+
+ }
+
+ if ( sServiceName.isEmpty() )
+ return;
+
+ // old formats are found ... using HumanPresentableName!
+ if( !sHumanName.isEmpty() )
+ {
+ nClipboardId = SotExchange::RegisterFormatName( sHumanName );
+
+ // For external filters ignore clipboard IDs
+ if(nFlags & SfxFilterFlags::STARONEFILTER)
+ {
+ nClipboardId = SotClipboardFormatId::NONE;
+ }
+ }
+ // register SfxFilter
+ // first erase module name from old filter names!
+ // e.g: "scalc: DIF" => "DIF"
+ sal_Int32 nStartRealName = sFilterName.indexOf( ": " );
+ if( nStartRealName != -1 )
+ {
+ SAL_WARN( "sfx.bastyp", "Old format, not supported!");
+ sFilterName = sFilterName.copy( nStartRealName+2 );
+ }
+
+ std::shared_ptr<const SfxFilter> pFilter = bUpdate ? SfxFilter::GetFilterByName( sFilterName ) : nullptr;
+ if (!pFilter)
+ {
+ pFilter = std::make_shared<SfxFilter>( sFilterName ,
+ sExtension ,
+ nFlags ,
+ nClipboardId ,
+ sType ,
+ sMimeType ,
+ sUserData ,
+ sServiceName ,
+ bEnabled );
+ rList.push_back( pFilter );
+ }
+ else
+ {
+ SfxFilter* pFilt = const_cast<SfxFilter*>(pFilter.get());
+ pFilt->maFilterName = sFilterName;
+ pFilt->aWildCard = WildCard(sExtension, ';');
+ pFilt->nFormatType = nFlags;
+ pFilt->lFormat = nClipboardId;
+ pFilt->aTypeName = sType;
+ pFilt->aMimeType = sMimeType;
+ pFilt->aUserData = sUserData;
+ pFilt->aServiceName = sServiceName;
+ pFilt->mbEnabled = bEnabled;
+ }
+
+ SfxFilter* pFilt = const_cast<SfxFilter*>(pFilter.get());
+
+ // Don't forget to set right UIName!
+ // Otherwise internal name is used as fallback ...
+ pFilt->SetUIName( sUIName );
+ pFilt->SetDefaultTemplate( sDefaultTemplate );
+ if( nFormatVersion )
+ {
+ pFilt->SetVersion( nFormatVersion );
+ }
+}
+
+void SfxFilterContainer::ReadFilters_Impl( bool bUpdate )
+{
+ if ( !pFilterArr )
+ CreateFilterArr();
+
+ bFirstRead = false;
+ SfxFilterList_Impl& rList = *pFilterArr;
+
+ try
+ {
+ // get the FilterFactory service to access the registered filters ... and types!
+ uno::Reference< lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory();
+ uno::Reference< container::XNameAccess > xFilterCFG ;
+ uno::Reference< container::XNameAccess > xTypeCFG ;
+ if( xServiceManager.is() )
+ {
+ xFilterCFG.set( xServiceManager->createInstance( "com.sun.star.document.FilterFactory" ), uno::UNO_QUERY );
+ xTypeCFG.set( xServiceManager->createInstance( "com.sun.star.document.TypeDetection" ), uno::UNO_QUERY );
+ }
+
+ if( xFilterCFG.is() && xTypeCFG.is() )
+ {
+ // select right query to get right set of filters for search module
+ const uno::Sequence< OUString > lFilterNames = xFilterCFG->getElementNames();
+ if ( lFilterNames.hasElements() )
+ {
+ // If list of filters already exist ...
+ // ReadExternalFilters must work in update mode.
+ // Best way seems to mark all filters NOT_INSTALLED
+ // and change it back for all valid filters afterwards.
+ if( !rList.empty() )
+ {
+ bUpdate = true;
+ for (const std::shared_ptr<const SfxFilter>& pFilter : rList)
+ {
+ SfxFilter* pNonConstFilter = const_cast<SfxFilter*>(pFilter.get());
+ pNonConstFilter->nFormatType |= SFX_FILTER_NOTINSTALLED;
+ }
+ }
+
+ // get all properties of filters ... put it into the filter container
+ for( const OUString& sFilterName : lFilterNames )
+ {
+ // Try to get filter .. but look for any exceptions!
+ // May be filter was deleted by another thread ...
+ ReadSingleFilter_Impl( sFilterName, xTypeCFG, xFilterCFG, bUpdate );
+ }
+ }
+ }
+ }
+ catch(const uno::Exception&)
+ {
+ SAL_WARN( "sfx.bastyp", "SfxFilterContainer::ReadFilter()\nException detected. Possible not all filters could be cached." );
+ }
+
+ if ( bUpdate )
+ {
+ // global filter array was modified, factory specific ones might need an
+ // update too
+ for (const auto& aImpl : aImplArr)
+ aImpl->Update();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sfx2/source/bastyp/fltlst.cxx b/sfx2/source/bastyp/fltlst.cxx
new file mode 100644
index 000000000..ac7f7df39
--- /dev/null
+++ b/sfx2/source/bastyp/fltlst.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/.
+ *
+ * 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 "fltlst.hxx"
+
+#include <com/sun/star/document/FilterConfigRefresh.hpp>
+#include <comphelper/processfactory.hxx>
+
+#include <sfx2/fcontnr.hxx>
+
+#include <vcl/svapp.hxx>
+#include <cppuhelper/implbase.hxx>
+
+
+// namespaces
+
+using namespace ::com::sun::star;
+
+namespace {
+
+class SfxRefreshListener : public ::cppu::WeakImplHelper<css::util::XRefreshListener>
+{
+ private:
+ SfxFilterListener *m_pOwner;
+
+ public:
+ explicit SfxRefreshListener(SfxFilterListener *pOwner)
+ : m_pOwner(pOwner)
+ {
+ }
+
+ // util.XRefreshListener
+ virtual void SAL_CALL refreshed( const css::lang::EventObject& rEvent ) override
+ {
+ m_pOwner->refreshed(rEvent);
+ }
+
+ // lang.XEventListener
+ virtual void SAL_CALL disposing(const css::lang::EventObject& rEvent) override
+ {
+ m_pOwner->disposing(rEvent);
+ }
+};
+
+}
+
+/*-************************************************************************************************************
+ @short ctor
+ @descr These initialize an instance of a SfxFilterListener class. Created object listen automatically
+ on right FilterFactory-Service for all changes and synchronize right SfxFilterContainer with
+ corresponding framework-cache.
+ We use given "sFactory" value to decide which query must be used to fill "pContainer" with new values.
+ Given "pContainer" hold us alive as uno reference and we use it to synchronize it with framework caches.
+ We will die, if he die! see dtor for further information.
+
+ @seealso dtor
+ @seealso class framework::FilterCache
+ @seealso service ::document::FilterFactory
+
+ @param "sFactory" , short name of module which contains filter container
+ @param "pContainer", pointer to filter container which will be informed
+ @onerror We show some assertions in non product version.
+ Otherwise we do nothing!
+ @threadsafe yes
+*//*-*************************************************************************************************************/
+SfxFilterListener::SfxFilterListener()
+ : m_xFilterCache(document::FilterConfigRefresh::create( comphelper::getProcessComponentContext() ) ),
+ m_xFilterCacheListener(new SfxRefreshListener(this))
+{
+ m_xFilterCache->addRefreshListener( m_xFilterCacheListener );
+}
+
+SfxFilterListener::~SfxFilterListener()
+{
+}
+
+void SfxFilterListener::refreshed( const lang::EventObject& aSource )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< util::XRefreshable > xContainer( aSource.Source, uno::UNO_QUERY );
+ if(
+ (xContainer.is() ) &&
+ (xContainer==m_xFilterCache)
+ )
+ {
+ SfxFilterContainer::ReadFilters_Impl( true );
+ }
+}
+
+void SfxFilterListener::disposing( const lang::EventObject& aSource )
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< util::XRefreshable > xNotifier( aSource.Source, uno::UNO_QUERY );
+ if (!xNotifier.is())
+ return;
+
+ if (xNotifier == m_xFilterCache)
+ m_xFilterCache.clear();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sfx2/source/bastyp/fltlst.hxx b/sfx2/source/bastyp/fltlst.hxx
new file mode 100644
index 000000000..69dbaf599
--- /dev/null
+++ b/sfx2/source/bastyp/fltlst.hxx
@@ -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/.
+ *
+ * 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_SFX2_SOURCE_BASTYP_FLTLST_HXX
+#define INCLUDED_SFX2_SOURCE_BASTYP_FLTLST_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/util/XRefreshable.hpp>
+#include <com/sun/star/util/XRefreshListener.hpp>
+#include <com/sun/star/lang/EventObject.hpp>
+
+class SfxFilterListener final
+{
+ private:
+ css::uno::Reference< css::util::XRefreshable > m_xFilterCache;
+ css::uno::Reference< css::util::XRefreshListener > m_xFilterCacheListener;
+
+ public:
+ SfxFilterListener();
+ ~SfxFilterListener();
+
+ public:
+ // XRefreshListener
+ /// @throws css::uno::RuntimeException
+ void refreshed( const css::lang::EventObject& aSource );
+ // XEventListener
+ /// @throws css::uno::RuntimeException
+ void disposing( const css::lang::EventObject& aSource );
+
+};
+
+#endif // INCLUDED_SFX2_SOURCE_BASTYP_FLTLST_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sfx2/source/bastyp/frmhtml.cxx b/sfx2/source/bastyp/frmhtml.cxx
new file mode 100644
index 000000000..a15a6cc7a
--- /dev/null
+++ b/sfx2/source/bastyp/frmhtml.cxx
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <svtools/htmltokn.h>
+
+#include <sfx2/frmdescr.hxx>
+#include <sfx2/frmhtml.hxx>
+
+char const sHTML_SC_yes[] = "YES";
+char const sHTML_SC_no[] = "NO";
+char const sHTML_SC_auto[] = "AUTO";
+
+HTMLOptionEnum<ScrollingMode> const aScrollingTable[] =
+{
+ { sHTML_SC_yes, ScrollingMode::Yes },
+ { sHTML_SC_no, ScrollingMode::No },
+ { sHTML_SC_auto, ScrollingMode::Auto },
+ { nullptr, ScrollingMode(0) }
+};
+
+namespace SfxFrameHTMLParser
+{
+void ParseFrameOptions(
+ SfxFrameDescriptor *pFrame, const HTMLOptions& rOptions, std::u16string_view rBaseURL )
+{
+ // Get and set the options
+ Size aMargin( pFrame->GetMargin() );
+
+ // Netscape seems to set marginwidth to 0 as soon as
+ // marginheight is set, and vice versa.
+ // Netscape does however not allow for a direct
+ // setting to 0, while IE4.0 does
+ // We will not mimic that bug !
+ bool bMarginWidth = false, bMarginHeight = false;
+
+ for (const auto & rOption : rOptions)
+ {
+ switch( rOption.GetToken() )
+ {
+ case HtmlOptionId::SRC:
+ pFrame->SetURL(
+ INetURLObject::GetAbsURL(
+ rBaseURL, rOption.GetString()) );
+ break;
+ case HtmlOptionId::NAME:
+ pFrame->SetName( rOption.GetString() );
+ break;
+ case HtmlOptionId::MARGINWIDTH:
+ aMargin.setWidth( rOption.GetNumber() );
+
+ if( !bMarginHeight )
+ aMargin.setHeight( 0 );
+ bMarginWidth = true;
+ break;
+ case HtmlOptionId::MARGINHEIGHT:
+ aMargin.setHeight( rOption.GetNumber() );
+
+ if( !bMarginWidth )
+ aMargin.setWidth( 0 );
+ bMarginHeight = true;
+ break;
+ case HtmlOptionId::SCROLLING:
+ pFrame->SetScrollingMode( rOption.GetEnum( aScrollingTable, ScrollingMode::Auto ) );
+ break;
+ case HtmlOptionId::FRAMEBORDER:
+ {
+ const OUString& aStr = rOption.GetString();
+ bool bBorder = true;
+ if ( aStr.equalsIgnoreAsciiCase("NO") ||
+ aStr.equalsIgnoreAsciiCase("0") )
+ bBorder = false;
+ pFrame->SetFrameBorder( bBorder );
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ pFrame->SetMargin( aMargin );
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sfx2/source/bastyp/frmhtmlw.cxx b/sfx2/source/bastyp/frmhtmlw.cxx
new file mode 100644
index 000000000..d568b1930
--- /dev/null
+++ b/sfx2/source/bastyp/frmhtmlw.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/.
+ *
+ * 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 <svtools/htmlkywd.hxx>
+
+#include <rtl/tencinfo.h>
+#include <sal/log.hxx>
+
+#include <svl/urihelper.hxx>
+#include <tools/stream.hxx>
+#include <tools/debug.hxx>
+#include <unotools/resmgr.hxx>
+#include <svtools/htmlout.hxx>
+
+#include <sfx2/frmdescr.hxx>
+#include <sfx2/frmhtmlw.hxx>
+#include <strings.hxx>
+
+#include <comphelper/processfactory.hxx>
+#include <comphelper/string.hxx>
+
+#include <com/sun/star/script/Converter.hpp>
+#include <com/sun/star/document/XDocumentProperties.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+#include <rtl/bootstrap.hxx>
+#include <rtl/strbuf.hxx>
+#include <sax/tools/converter.hxx>
+
+using namespace ::com::sun::star;
+
+char const sHTML_SC_yes[] = "YES";
+char const sHTML_SC_no[] = "NO";
+
+void SfxFrameHTMLWriter::OutMeta( SvStream& rStrm,
+ const char *pIndent,
+ const OUString& rName,
+ const OUString& rContent,
+ bool bHTTPEquiv,
+ OUString *pNonConvertableChars )
+{
+ rStrm.WriteCharPtr( SAL_NEWLINE_STRING );
+ if( pIndent )
+ rStrm.WriteCharPtr( pIndent );
+
+ OStringBuffer sOut;
+ sOut.append("<" OOO_STRING_SVTOOLS_HTML_meta " ")
+ .append(bHTTPEquiv ? OOO_STRING_SVTOOLS_HTML_O_httpequiv : OOO_STRING_SVTOOLS_HTML_O_name).append("=\"");
+ rStrm.WriteOString( sOut.makeStringAndClear() );
+
+ HTMLOutFuncs::Out_String( rStrm, rName, pNonConvertableChars );
+
+ sOut.append("\" " OOO_STRING_SVTOOLS_HTML_O_content "=\"");
+ rStrm.WriteOString( sOut.makeStringAndClear() );
+
+ HTMLOutFuncs::Out_String( rStrm, rContent, pNonConvertableChars ).WriteCharPtr( "\"/>" );
+}
+
+void SfxFrameHTMLWriter::Out_DocInfo( SvStream& rStrm, const OUString& rBaseURL,
+ const uno::Reference<document::XDocumentProperties> & i_xDocProps,
+ const char *pIndent,
+ OUString *pNonConvertableChars )
+{
+ OutMeta( rStrm, pIndent, OOO_STRING_SVTOOLS_HTML_META_content_type, "text/html; charset=utf-8", true,
+ pNonConvertableChars );
+
+ // Title (regardless if empty)
+ rStrm.WriteCharPtr( SAL_NEWLINE_STRING );
+ if( pIndent )
+ rStrm.WriteCharPtr( pIndent );
+ HTMLOutFuncs::Out_AsciiTag( rStrm, OOO_STRING_SVTOOLS_HTML_title );
+ if( i_xDocProps.is() )
+ {
+ const OUString& rTitle = i_xDocProps->getTitle();
+ if( !rTitle.isEmpty() )
+ HTMLOutFuncs::Out_String( rStrm, rTitle, pNonConvertableChars );
+ }
+ HTMLOutFuncs::Out_AsciiTag( rStrm, OOO_STRING_SVTOOLS_HTML_title, false );
+
+ // Target-Frame
+ if( i_xDocProps.is() )
+ {
+ const OUString& rTarget = i_xDocProps->getDefaultTarget();
+ if( !rTarget.isEmpty() )
+ {
+ rStrm.WriteCharPtr( SAL_NEWLINE_STRING );
+ if( pIndent )
+ rStrm.WriteCharPtr( pIndent );
+
+ rStrm.WriteOString( "<" OOO_STRING_SVTOOLS_HTML_base " "
+ OOO_STRING_SVTOOLS_HTML_O_target "=\"" );
+ HTMLOutFuncs::Out_String( rStrm, rTarget, pNonConvertableChars )
+ .WriteCharPtr( "\">" );
+ }
+ }
+
+ // Who we are
+ OUString sGenerator(Translate::ExpandVariables(STR_HTML_GENERATOR));
+ OUString os( "$_OS" );
+ ::rtl::Bootstrap::expandMacros(os);
+ sGenerator = sGenerator.replaceFirst( "%1", os );
+ OutMeta( rStrm, pIndent, OOO_STRING_SVTOOLS_HTML_META_generator, sGenerator, false, pNonConvertableChars );
+
+ if( !i_xDocProps.is() )
+ return;
+
+ // Reload
+ if( (i_xDocProps->getAutoloadSecs() != 0) ||
+ !i_xDocProps->getAutoloadURL().isEmpty() )
+ {
+ OUString sContent = OUString::number(
+ i_xDocProps->getAutoloadSecs() );
+
+ const OUString &rReloadURL = i_xDocProps->getAutoloadURL();
+ if( !rReloadURL.isEmpty() )
+ {
+ sContent += ";URL=" + URIHelper::simpleNormalizedMakeRelative(
+ rBaseURL, rReloadURL);
+ }
+
+ OutMeta( rStrm, pIndent, OOO_STRING_SVTOOLS_HTML_META_refresh, sContent, true,
+ pNonConvertableChars );
+ }
+
+ // Author
+ const OUString& rAuthor = i_xDocProps->getAuthor();
+ if( !rAuthor.isEmpty() )
+ OutMeta( rStrm, pIndent, OOO_STRING_SVTOOLS_HTML_META_author, rAuthor, false,
+ pNonConvertableChars );
+
+ // created
+ ::util::DateTime uDT = i_xDocProps->getCreationDate();
+ OUStringBuffer aBuffer;
+ ::sax::Converter::convertTimeOrDateTime(aBuffer, uDT);
+
+ OutMeta( rStrm, pIndent, OOO_STRING_SVTOOLS_HTML_META_created, aBuffer.makeStringAndClear(), false,
+ pNonConvertableChars );
+
+ // changedby
+ const OUString& rChangedBy = i_xDocProps->getModifiedBy();
+ if( !rChangedBy.isEmpty() )
+ OutMeta( rStrm, pIndent, OOO_STRING_SVTOOLS_HTML_META_changedby, rChangedBy, false,
+ pNonConvertableChars );
+
+ // changed
+ uDT = i_xDocProps->getModificationDate();
+ ::sax::Converter::convertTimeOrDateTime(aBuffer, uDT);
+
+ OutMeta( rStrm, pIndent, OOO_STRING_SVTOOLS_HTML_META_changed, aBuffer.makeStringAndClear(), false,
+ pNonConvertableChars );
+
+ // Subject
+ const OUString& rTheme = i_xDocProps->getSubject();
+ if( !rTheme.isEmpty() )
+ OutMeta( rStrm, pIndent, OOO_STRING_SVTOOLS_HTML_META_classification, rTheme, false,
+ pNonConvertableChars );
+
+ // Description
+ const OUString& rComment = i_xDocProps->getDescription();
+ if( !rComment.isEmpty() )
+ OutMeta( rStrm, pIndent, OOO_STRING_SVTOOLS_HTML_META_description, rComment, false,
+ pNonConvertableChars);
+
+ // Keywords
+ OUString Keywords = ::comphelper::string::convertCommaSeparated(
+ i_xDocProps->getKeywords());
+ if( !Keywords.isEmpty() )
+ OutMeta( rStrm, pIndent, OOO_STRING_SVTOOLS_HTML_META_keywords, Keywords, false,
+ pNonConvertableChars);
+
+ uno::Reference < script::XTypeConverter > xConverter( script::Converter::create(
+ ::comphelper::getProcessComponentContext() ) );
+ uno::Reference<beans::XPropertySet> xUserDefinedProps(
+ i_xDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW);
+ uno::Reference<beans::XPropertySetInfo> xPropInfo =
+ xUserDefinedProps->getPropertySetInfo();
+ DBG_ASSERT(xPropInfo.is(), "UserDefinedProperties Info is null");
+ const uno::Sequence<beans::Property> props = xPropInfo->getProperties();
+ for (const auto& rProp : props)
+ {
+ try
+ {
+ OUString name = rProp.Name;
+ uno::Any aStr = xConverter->convertToSimpleType(
+ xUserDefinedProps->getPropertyValue(name),
+ uno::TypeClass_STRING);
+ OUString str;
+ aStr >>= str;
+ OUString valstr(comphelper::string::stripEnd(str, ' '));
+ OutMeta( rStrm, pIndent, name, valstr, false,
+ pNonConvertableChars );
+ }
+ catch (const uno::Exception&)
+ {
+ // may happen with concurrent modification...
+ SAL_INFO("sfx", "SfxFrameHTMLWriter::Out_DocInfo: exception");
+ }
+ }
+}
+
+void SfxFrameHTMLWriter::Out_FrameDescriptor(
+ SvStream& rOut, const OUString& rBaseURL, const uno::Reference < beans::XPropertySet >& xSet,
+ OUString *pNonConvertableChars )
+{
+ try
+ {
+ OStringBuffer sOut;
+ OUString aStr;
+ uno::Any aAny = xSet->getPropertyValue("FrameURL");
+ if ( (aAny >>= aStr) && !aStr.isEmpty() )
+ {
+ OUString aURL = INetURLObject( aStr ).GetMainURL( INetURLObject::DecodeMechanism::ToIUri );
+ if( !aURL.isEmpty() )
+ {
+ aURL = URIHelper::simpleNormalizedMakeRelative(
+ rBaseURL, aURL );
+ sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_src "=\"");
+ rOut.WriteOString( sOut.makeStringAndClear() );
+ HTMLOutFuncs::Out_String( rOut, aURL, pNonConvertableChars );
+ sOut.append('\"');
+ }
+ }
+
+ aAny = xSet->getPropertyValue("FrameName");
+ if ( (aAny >>= aStr) && !aStr.isEmpty() )
+ {
+ sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_name "=\"");
+ rOut.WriteOString( sOut.makeStringAndClear() );
+ HTMLOutFuncs::Out_String( rOut, aStr, pNonConvertableChars );
+ sOut.append('\"');
+ }
+
+ sal_Int32 nVal = SIZE_NOT_SET;
+ aAny = xSet->getPropertyValue("FrameMarginWidth");
+ if ( (aAny >>= nVal) && nVal != SIZE_NOT_SET )
+ {
+ sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_marginwidth)
+ .append('=').append(nVal);
+ }
+ aAny = xSet->getPropertyValue("FrameMarginHeight");
+ if ( (aAny >>= nVal) && nVal != SIZE_NOT_SET )
+ {
+ sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_marginheight)
+ .append('=').append(nVal);
+ }
+
+ bool bVal = true;
+ aAny = xSet->getPropertyValue("FrameIsAutoScroll");
+ if ( (aAny >>= bVal) && !bVal )
+ {
+ aAny = xSet->getPropertyValue("FrameIsScrollingMode");
+ if ( aAny >>= bVal )
+ {
+ const char *pStr = bVal ? sHTML_SC_yes : sHTML_SC_no;
+ sOut.append(OString::Concat(" " OOO_STRING_SVTOOLS_HTML_O_scrolling) +
+ pStr);
+ }
+ }
+
+ // frame border (MS+Netscape-Extension)
+ aAny = xSet->getPropertyValue("FrameIsAutoBorder");
+ if ( (aAny >>= bVal) && !bVal )
+ {
+ aAny = xSet->getPropertyValue("FrameIsBorder");
+ if ( aAny >>= bVal )
+ {
+ const char* pStr = bVal ? sHTML_SC_yes : sHTML_SC_no;
+ sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_frameborder)
+ .append('=').append(pStr);
+ }
+ }
+ rOut.WriteOString( sOut.makeStringAndClear() );
+ }
+ catch (const uno::Exception&)
+ {
+ }
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sfx2/source/bastyp/helper.cxx b/sfx2/source/bastyp/helper.cxx
new file mode 100644
index 000000000..96f3b67f1
--- /dev/null
+++ b/sfx2/source/bastyp/helper.cxx
@@ -0,0 +1,229 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <helper.hxx>
+#include <com/sun/star/sdbc/XResultSet.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/task/InteractionHandler.hpp>
+#include <com/sun/star/ucb/CommandAbortedException.hpp>
+#include <com/sun/star/ucb/XContentAccess.hpp>
+#include <com/sun/star/ucb/XDynamicResultSet.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <sal/log.hxx>
+#include <tools/diagnose_ex.h>
+#include <tools/debug.hxx>
+#include <tools/urlobj.hxx>
+#include <ucbhelper/content.hxx>
+#include <ucbhelper/commandenvironment.hxx>
+#include <comphelper/processfactory.hxx>
+
+using namespace com::sun::star;
+using namespace comphelper;
+using namespace osl;
+
+using ::std::vector;
+
+
+std::vector<OUString> SfxContentHelper::GetResultSet( const OUString& rURL )
+{
+ vector<OUString> aList;
+ try
+ {
+ ::ucbhelper::Content aCnt( rURL, uno::Reference< ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext() );
+ uno::Reference< sdbc::XResultSet > xResultSet;
+ uno::Reference< ucb::XDynamicResultSet > xDynResultSet;
+
+ try
+ {
+ xDynResultSet = aCnt.createDynamicCursor( { "Title", "ContentType", "IsFolder" } );
+ if ( xDynResultSet.is() )
+ xResultSet = xDynResultSet->getStaticResultSet();
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "sfx.bastyp", "GetResultSet" );
+ }
+
+
+ if ( xResultSet.is() )
+ {
+ uno::Reference< sdbc::XRow > xRow( xResultSet, uno::UNO_QUERY );
+ uno::Reference< ucb::XContentAccess > xContentAccess( xResultSet, uno::UNO_QUERY );
+
+ try
+ {
+ while ( xResultSet->next() )
+ {
+ OUString aTitle( xRow->getString(1) );
+ OUString aType( xRow->getString(2) );
+ OUString aRow = aTitle +
+ "\t" +
+ aType +
+ "\t" +
+ xContentAccess->queryContentIdentifierString();
+ aList.push_back( aRow );
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "sfx.bastyp", "XContentAccess::next()" );
+ }
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "sfx.bastyp", "GetResultSet");
+ }
+
+ return aList;
+}
+
+
+std::vector< OUString > SfxContentHelper::GetHelpTreeViewContents( const OUString& rURL )
+{
+ vector< OUString > aProperties;
+ try
+ {
+ uno::Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
+ uno::Reference< task::XInteractionHandler > xInteractionHandler(
+ task::InteractionHandler::createWithParent(xContext, nullptr), uno::UNO_QUERY_THROW );
+
+ ::ucbhelper::Content aCnt( rURL, new ::ucbhelper::CommandEnvironment( xInteractionHandler, uno::Reference< ucb::XProgressHandler >() ), comphelper::getProcessComponentContext() );
+ uno::Reference< sdbc::XResultSet > xResultSet;
+
+ try
+ {
+ uno::Reference< ucb::XDynamicResultSet > xDynResultSet = aCnt.createDynamicCursor( { "Title", "IsFolder" } );
+ if ( xDynResultSet.is() )
+ xResultSet = xDynResultSet->getStaticResultSet();
+ }
+ catch( const ucb::CommandAbortedException& )
+ {
+ }
+ catch( const uno::Exception& )
+ {
+ }
+
+ if ( xResultSet.is() )
+ {
+ uno::Reference< sdbc::XRow > xRow( xResultSet, uno::UNO_QUERY );
+ uno::Reference< ucb::XContentAccess > xContentAccess( xResultSet, uno::UNO_QUERY );
+
+ try
+ {
+ while ( xResultSet->next() )
+ {
+ OUString aTitle( xRow->getString(1) );
+ bool bFolder = xRow->getBoolean(2);
+ OUString aRow = aTitle + "\t" +
+ xContentAccess->queryContentIdentifierString() + "\t" +
+ (bFolder ? std::u16string_view(u"1") : std::u16string_view(u"0"));
+ aProperties.push_back( aRow );
+ }
+ }
+ catch( const ucb::CommandAbortedException& )
+ {
+ }
+ catch( const uno::Exception& )
+ {
+ }
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ }
+
+ return aProperties;
+}
+
+
+OUString SfxContentHelper::GetActiveHelpString( const OUString& rURL )
+{
+ OUStringBuffer aRet;
+ try
+ {
+ uno::Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
+ uno::Reference< task::XInteractionHandler > xInteractionHandler(
+ task::InteractionHandler::createWithParent(xContext, nullptr), uno::UNO_QUERY_THROW );
+ ::ucbhelper::Content aCnt( rURL, new ::ucbhelper::CommandEnvironment( xInteractionHandler, uno::Reference< ucb::XProgressHandler >() ), comphelper::getProcessComponentContext() );
+ // open the "active help" stream
+ uno::Reference< io::XInputStream > xStream = aCnt.openStream();
+ // and convert it to a String
+ uno::Sequence< sal_Int8 > lData;
+ sal_Int32 nRead = xStream->readBytes( lData, 1024 );
+ while ( nRead > 0 )
+ {
+ OString sOldString( reinterpret_cast<char const *>(lData.getConstArray()), nRead );
+ OUString sString = OStringToOUString( sOldString, RTL_TEXTENCODING_UTF8 );
+ aRet.append( sString );
+
+ nRead = xStream->readBytes( lData, 1024 );
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ }
+
+ return aRet.makeStringAndClear();
+}
+
+
+bool SfxContentHelper::IsHelpErrorDocument( std::u16string_view rURL )
+{
+ bool bRet = false;
+ try
+ {
+ ::ucbhelper::Content aCnt( INetURLObject( rURL ).GetMainURL( INetURLObject::DecodeMechanism::NONE ),
+ uno::Reference< ucb::XCommandEnvironment >(),
+ comphelper::getProcessComponentContext() );
+ if ( !( aCnt.getPropertyValue( "IsErrorDocument" ) >>= bRet ) )
+ {
+ SAL_WARN( "sfx.bastyp", "Property 'IsErrorDocument' is missing" );
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ }
+
+ return bRet;
+}
+
+
+sal_Int64 SfxContentHelper::GetSize( std::u16string_view rContent )
+{
+ sal_Int64 nSize = 0;
+ INetURLObject aObj( rContent );
+ DBG_ASSERT( aObj.GetProtocol() != INetProtocol::NotValid, "Invalid URL!" );
+ try
+ {
+ ::ucbhelper::Content aCnt( aObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ), uno::Reference< ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext() );
+ aCnt.getPropertyValue( "Size" ) >>= nSize;
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "sfx.bastyp", "" );
+ }
+ return nSize;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sfx2/source/bastyp/mieclip.cxx b/sfx2/source/bastyp/mieclip.cxx
new file mode 100644
index 000000000..e40c5bd29
--- /dev/null
+++ b/sfx2/source/bastyp/mieclip.cxx
@@ -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 .
+ */
+
+#include <sal/config.h>
+
+#include <o3tl/safeint.hxx>
+#include <o3tl/string_view.hxx>
+#include <tools/stream.hxx>
+#include <comphelper/string.hxx>
+
+#include <sfx2/mieclip.hxx>
+
+MSE40HTMLClipFormatObj::~MSE40HTMLClipFormatObj()
+{
+}
+
+SvStream* MSE40HTMLClipFormatObj::IsValid( SvStream& rStream )
+{
+ bool bRet = false;
+ pStrm.reset();
+
+ OStringBuffer sLine;
+ sal_Int32 nStt = -1, nEnd = -1, nFragStart = -1, nFragEnd = -1;
+ sal_Int32 nIndex = 0;
+
+ rStream.Seek(STREAM_SEEK_TO_BEGIN);
+ rStream.ResetError();
+
+ if( rStream.ReadLine( sLine ) &&
+ o3tl::getToken(sLine, 0, ':', nIndex ) == "Version" )
+ {
+ while( rStream.ReadLine( sLine ) )
+ {
+ nIndex = 0;
+ std::string_view sTmp(o3tl::getToken(sLine, 0, ':', nIndex));
+ std::string_view sView(sLine);
+ if (sTmp == "StartHTML")
+ nStt = o3tl::toInt32(sView.substr(nIndex));
+ else if (sTmp == "EndHTML")
+ nEnd = o3tl::toInt32(sView.substr(nIndex));
+ else if (sTmp == "StartFragment")
+ nFragStart = o3tl::toInt32(sView.substr(nIndex));
+ else if (sTmp == "EndFragment")
+ nFragEnd = o3tl::toInt32(sView.substr(nIndex));
+ else if (sTmp == "SourceURL")
+ sBaseURL = OStringToOUString( sView.substr(nIndex), RTL_TEXTENCODING_UTF8 );
+
+ if (nEnd >= 0 && nStt >= 0 &&
+ (!sBaseURL.isEmpty() || rStream.Tell() >= o3tl::make_unsigned(nStt)))
+ {
+ bRet = true;
+ break;
+ }
+ }
+ }
+
+ if( bRet )
+ {
+ rStream.Seek( nStt );
+
+ pStrm.reset( new SvMemoryStream( ( nEnd - nStt < 0x10000l
+ ? nEnd - nStt + 32
+ : 0 )) );
+ pStrm->WriteStream( rStream );
+ pStrm->SetStreamSize( nEnd - nStt + 1 );
+ pStrm->Seek( STREAM_SEEK_TO_BEGIN );
+ return pStrm.get();
+ }
+
+ if (nFragStart > 0 && nFragEnd > 0 && nFragEnd > nFragStart)
+ {
+ size_t nSize = nFragEnd - nFragStart + 1;
+ if (nSize < 0x10000L)
+ {
+ rStream.Seek(nFragStart);
+ pStrm.reset( new SvMemoryStream(nSize) );
+ pStrm->WriteStream( rStream );
+ pStrm->SetStreamSize(nSize);
+ pStrm->Seek(STREAM_SEEK_TO_BEGIN);
+ return pStrm.get();
+ }
+ }
+
+ return nullptr;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sfx2/source/bastyp/progress.cxx b/sfx2/source/bastyp/progress.cxx
new file mode 100644
index 000000000..6d73d8316
--- /dev/null
+++ b/sfx2/source/bastyp/progress.cxx
@@ -0,0 +1,401 @@
+/* -*- 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 <sfx2/progress.hxx>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/task/XStatusIndicatorFactory.hpp>
+
+#include <svl/eitem.hxx>
+#include <tools/debug.hxx>
+#include <sal/log.hxx>
+
+#include <appdata.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/frame.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/objsh.hxx>
+#include <sfx2/app.hxx>
+#include <sfxtypes.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/sfxsids.hrc>
+#include <workwin.hxx>
+#include <sfxbasecontroller_internal.hxx>
+#include <time.h>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::task;
+
+struct SfxProgress_Impl
+{
+ Reference < XStatusIndicator > xStatusInd;
+ OUString aText;
+ sal_uInt32 nMax;
+ clock_t nCreate;
+ bool bWaitMode;
+ bool bRunning;
+
+ SfxProgress* pActiveProgress;
+ SfxObjectShellRef xObjSh;
+ SfxWorkWindow* pWorkWin;
+ SfxViewFrame* pView;
+
+ explicit SfxProgress_Impl();
+};
+
+SfxProgress_Impl::SfxProgress_Impl()
+ : nMax(0)
+ , nCreate(0)
+ , bWaitMode(false)
+ , bRunning(false)
+ , pActiveProgress(nullptr)
+ , pWorkWin(nullptr)
+ , pView(nullptr)
+{
+}
+
+
+SfxProgress::SfxProgress
+(
+ SfxObjectShell* pObjSh, /* The action is performed on the
+ SfxObjectShell which can be NULL.
+ When it is then the application will be
+ used */
+
+ const OUString& rText, /* Text, which appears before the Statusmonitor
+ in the status line */
+
+ sal_uInt32 nRange, /* Max value for range */
+
+ bool bWait /* Activate the wait-Pointer initially (TRUE) */
+)
+
+/* [Description]
+
+ The constructor of the class SfxProgress switches the SfxObjectShell
+ passed as parameter and SfxViewFrames which display this document in
+ a progress mode. Ie as long as one of those SfxViewFrame instances is
+ active the associated SfxDispatcher and associated Window is disabled.
+ A progress-bar will be displayed in the status bar,
+*/
+
+: pImpl( new SfxProgress_Impl ),
+ nVal(0),
+ bSuspended(true)
+{
+ pImpl->bRunning = true;
+
+ pImpl->xObjSh = pObjSh;
+ pImpl->aText = rText;
+ pImpl->nMax = nRange;
+ pImpl->bWaitMode = bWait;
+ pImpl->nCreate = Get10ThSec();
+ SAL_INFO(
+ "sfx.bastyp",
+ "SfxProgress: created for '" << rText << "' at " << pImpl->nCreate
+ << "ds");
+ pImpl->pWorkWin = nullptr;
+ pImpl->pView = nullptr;
+
+ pImpl->pActiveProgress = GetActiveProgress( pObjSh );
+ if ( pObjSh )
+ pObjSh->SetProgress_Impl(this);
+ else if( !pImpl->pActiveProgress )
+ SfxGetpApp()->SetProgress_Impl(this);
+ Resume();
+}
+
+
+SfxProgress::~SfxProgress()
+
+/* [Description]
+
+ The destructor of the class SfxProgress restores the old status,
+ the documents are released again and the status bar shows the items again.
+*/
+
+{
+ Stop();
+ if ( pImpl->xStatusInd.is() )
+ pImpl->xStatusInd->end();
+}
+
+
+void SfxProgress::Stop()
+
+/* [Description]
+
+ Early Exit of <SfxProgress>.
+*/
+
+{
+ if( pImpl->pActiveProgress )
+ {
+ if ( pImpl->xObjSh.is() && pImpl->xObjSh->GetProgress() == this )
+ pImpl->xObjSh->SetProgress_Impl(nullptr);
+ return;
+ }
+
+ if ( !pImpl->bRunning )
+ return;
+ pImpl->bRunning = false;
+ SAL_INFO(
+ "sfx.bastyp", "SfxProgress: destroyed at " << Get10ThSec() << "ds");
+
+ Suspend();
+ if ( pImpl->xObjSh.is() )
+ pImpl->xObjSh->SetProgress_Impl(nullptr);
+ else
+ SfxGetpApp()->SetProgress_Impl(nullptr);
+}
+
+void SfxProgress::SetState
+(
+ sal_uInt32 nNewVal, /* new value for the progress bar */
+
+ sal_uInt32 nNewRange /* new maximum value, 0 for retaining the old */
+)
+/* [Description]
+
+ Setting the current status, after a time delay Reschedule is called.
+*/
+
+{
+ if( pImpl->pActiveProgress ) return;
+
+ nVal = nNewVal;
+
+ // new Range?
+ if ( nNewRange && nNewRange != pImpl->nMax )
+ {
+ SAL_INFO(
+ "sfx.bastyp",
+ "SfxProgress: range changed from " << pImpl->nMax << " to "
+ << nNewRange);
+ pImpl->nMax = nNewRange;
+ }
+
+ if ( !pImpl->xStatusInd.is() )
+ {
+ // get the active ViewFrame of the document this progress is working on
+ // if it doesn't work on a document, take the current ViewFrame
+ SfxObjectShell* pObjSh = pImpl->xObjSh.get();
+ pImpl->pView = SfxViewFrame::Current();
+ DBG_ASSERT( pImpl->pView || pObjSh, "Can't make progress bar!");
+ if ( pObjSh && ( !pImpl->pView || pObjSh != pImpl->pView->GetObjectShell() ) )
+ {
+ // current document does not belong to current ViewFrame; take it's first visible ViewFrame
+ SfxViewFrame* pDocView = SfxViewFrame::GetFirst( pObjSh );
+ if ( pDocView )
+ pImpl->pView = pDocView;
+ else
+ {
+ // don't show status indicator for hidden documents (only valid while loading)
+ SfxMedium* pMedium = pObjSh->GetMedium();
+ const SfxBoolItem* pHiddenItem = SfxItemSet::GetItem<SfxBoolItem>(pMedium->GetItemSet(), SID_HIDDEN, false);
+ if ( !pHiddenItem || !pHiddenItem->GetValue() )
+ {
+ const SfxUnoAnyItem* pIndicatorItem = SfxItemSet::GetItem<SfxUnoAnyItem>(pMedium->GetItemSet(), SID_PROGRESS_STATUSBAR_CONTROL, false);
+ Reference< XStatusIndicator > xInd;
+ if ( pIndicatorItem && (pIndicatorItem->GetValue()>>=xInd) )
+ pImpl->xStatusInd = xInd;
+ }
+ }
+ }
+ else if ( pImpl->pView )
+ {
+ pImpl->pWorkWin = SfxGetpApp()->GetWorkWindow_Impl( pImpl->pView );
+ if ( pImpl->pWorkWin )
+ pImpl->xStatusInd = pImpl->pWorkWin->GetStatusIndicator();
+ }
+
+ if ( pImpl->xStatusInd.is() )
+ {
+ pImpl->xStatusInd->start( pImpl->aText, pImpl->nMax );
+ pImpl->pView = nullptr;
+ }
+ }
+
+ if ( pImpl->xStatusInd.is() )
+ {
+ pImpl->xStatusInd->setValue( nNewVal );
+ }
+}
+
+
+void SfxProgress::Resume()
+
+/* [Description]
+
+ Resumed the status of the display after an interrupt.
+
+ [Cross-reference]
+
+ <SfxProgress::Suspend()>
+*/
+
+{
+ if( pImpl->pActiveProgress ) return;
+ if ( !bSuspended )
+ return;
+
+ SAL_INFO("sfx.bastyp", "SfxProgress: resumed");
+ if ( pImpl->xStatusInd.is() )
+ {
+ pImpl->xStatusInd->start( pImpl->aText, pImpl->nMax );
+ pImpl->xStatusInd->setValue( nVal );
+ }
+
+ if ( pImpl->bWaitMode )
+ {
+ if ( pImpl->xObjSh.is() )
+ {
+ for ( SfxViewFrame *pFrame = SfxViewFrame::GetFirst(pImpl->xObjSh.get() );
+ pFrame;
+ pFrame = SfxViewFrame::GetNext( *pFrame, pImpl->xObjSh.get() ) )
+ pFrame->GetWindow().EnterWait();
+ }
+ }
+
+ if ( pImpl->xObjSh.is() )
+ {
+ SfxViewFrame *pFrame = SfxViewFrame::GetFirst(pImpl->xObjSh.get());
+ if ( pFrame )
+ pFrame->GetBindings().ENTERREGISTRATIONS();
+ }
+
+ bSuspended = false;
+}
+
+
+void SfxProgress::Suspend()
+
+/* [Description]
+
+ Interrupts the status of the display
+
+ [Cross-reference]
+
+ <SfxProgress::Resume()>
+*/
+
+{
+ if( pImpl->pActiveProgress ) return;
+ if ( bSuspended )
+ return;
+
+ SAL_INFO("sfx.bastyp", "SfxProgress: suspended");
+ bSuspended = true;
+
+ if ( pImpl->xStatusInd.is() )
+ {
+ pImpl->xStatusInd->reset();
+ }
+
+ if ( pImpl->xObjSh.is() )
+ {
+ for ( SfxViewFrame *pFrame =
+ SfxViewFrame::GetFirst(pImpl->xObjSh.get());
+ pFrame;
+ pFrame = SfxViewFrame::GetNext( *pFrame, pImpl->xObjSh.get() ) )
+ pFrame->GetWindow().LeaveWait();
+ }
+ if ( pImpl->xObjSh.is() )
+ {
+ SfxViewFrame *pFrame = SfxViewFrame::GetFirst( pImpl->xObjSh.get() );
+ if ( pFrame )
+ pFrame->GetBindings().LEAVEREGISTRATIONS();
+ }
+}
+
+
+void SfxProgress::Reschedule()
+
+/* [Description]
+
+ Reschedule, callable from the outside
+*/
+
+{
+ SFX_STACK(SfxProgress::Reschedule);
+}
+
+
+SfxProgress* SfxProgress::GetActiveProgress
+(
+ SfxObjectShell const * pDocSh /* the <SfxObjectShell>, which should be
+ queried after a current <SfxProgress>,
+ or 0 if a current SfxProgress for the
+ entire application should be obtained.
+ The pointer only needs at the time of
+ the call to be valid.
+ */
+)
+
+/* [Description]
+
+ This method is used to check whether and which <SfxProgress> is currently
+ active for a specific instance of SfxObjectShell or even an entire
+ application. This can for example be used to check for Time-Out-Events, etc.
+
+ Instead of a pointer to the SfxProgress the SfxObjectShell may be
+ pointed at the SfxProgress of the application, with the query
+ 'SfxProgress:: GetActiveProgress (pMyDocSh)' thus the current
+ SfxProgress of 'pMyDocSh' is delivered, otherwise the SfxProgress of
+ the application or a 0-pointer.
+
+ [Note]
+
+ If no SfxProgress is running in the application and also not at the
+ specified SfxObjectShell, then this method will always return 0,
+ even if one SfxProgress runs on another SfxObjectShell.
+
+ [Cross-reference]
+
+ <SfxApplication::GetProgress()const>
+ <SfxObjectShell::GetProgress()const>
+*/
+
+{
+ if ( !SfxApplication::Get() )
+ return nullptr;
+
+ SfxProgress *pProgress = nullptr;
+ if ( pDocSh )
+ pProgress = pDocSh->GetProgress();
+ if ( !pProgress )
+ pProgress = SfxGetpApp()->GetProgress();
+ return pProgress;
+}
+
+
+void SfxProgress::EnterLock()
+{
+ SfxGetpApp()->Get_Impl()->nRescheduleLocks++;
+}
+
+
+void SfxProgress::LeaveLock()
+{
+ SfxAppData_Impl *pImp = SfxGetpApp()->Get_Impl();
+ DBG_ASSERT( 0 != pImp->nRescheduleLocks, "SFxProgress::LeaveLock but no locks" );
+ pImp->nRescheduleLocks--;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sfx2/source/bastyp/sfxhtml.cxx b/sfx2/source/bastyp/sfxhtml.cxx
new file mode 100644
index 000000000..5907a660b
--- /dev/null
+++ b/sfx2/source/bastyp/sfxhtml.cxx
@@ -0,0 +1,345 @@
+/* -*- 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 <tools/urlobj.hxx>
+#include <tools/debug.hxx>
+
+#include <sfx2/docfile.hxx>
+#include <sfx2/event.hxx>
+#include <openflag.hxx>
+
+#include <svl/numformat.hxx>
+#include <svtools/htmlkywd.hxx>
+#include <svtools/htmltokn.h>
+#include <vcl/imap.hxx>
+#include <vcl/imapcirc.hxx>
+#include <vcl/imapobj.hxx>
+#include <vcl/imappoly.hxx>
+#include <vcl/imaprect.hxx>
+#include <svl/zforlist.hxx>
+
+#include <sfx2/sfxhtml.hxx>
+
+#include <comphelper/string.hxx>
+#include <o3tl/string_view.hxx>
+
+#include <vector>
+
+
+using namespace ::com::sun::star;
+
+
+// <INPUT TYPE=xxx>
+HTMLOptionEnum<IMapObjectType> const aAreaShapeOptEnums[] =
+{
+ { OOO_STRING_SVTOOLS_HTML_SH_rect, IMapObjectType::Rectangle },
+ { OOO_STRING_SVTOOLS_HTML_SH_rectangle, IMapObjectType::Rectangle },
+ { OOO_STRING_SVTOOLS_HTML_SH_circ, IMapObjectType::Circle },
+ { OOO_STRING_SVTOOLS_HTML_SH_circle, IMapObjectType::Circle },
+ { OOO_STRING_SVTOOLS_HTML_SH_poly, IMapObjectType::Polygon },
+ { OOO_STRING_SVTOOLS_HTML_SH_polygon, IMapObjectType::Polygon },
+ { nullptr, IMapObjectType::Rectangle }
+};
+
+SfxHTMLParser::SfxHTMLParser( SvStream& rStream, bool bIsNewDoc,
+ SfxMedium *pMed )
+ : HTMLParser(rStream, bIsNewDoc)
+ , pMedium(pMed)
+ , eScriptType(STARBASIC)
+{
+ DBG_ASSERT( RTL_TEXTENCODING_UTF8 == GetSrcEncoding( ),
+ "SfxHTMLParser::SfxHTMLParser: From where comes ZS?" );
+
+ DBG_ASSERT( !IsSwitchToUCS2(),
+ "SfxHTMLParser::SfxHTMLParser: Switch to UCS2?" );
+
+ // If the file starts with a BOM, switch to UCS2.
+ SetSwitchToUCS2( true );
+}
+
+SfxHTMLParser::~SfxHTMLParser()
+{
+ DBG_ASSERT( !pDLMedium, "Here is a File Download that has got stuck" );
+}
+
+bool SfxHTMLParser::ParseMapOptions(
+ ImageMap* pImageMap, const HTMLOptions& rOptions)
+{
+ DBG_ASSERT( pImageMap, "ParseMapOptions: No Image-Map" );
+
+ OUString aName;
+
+ for (size_t i = rOptions.size(); i; )
+ {
+ const HTMLOption& aOption = rOptions[--i];
+ if ( aOption.GetToken() == HtmlOptionId::NAME )
+ aName = aOption.GetString();
+ }
+
+ if( !aName.isEmpty() )
+ pImageMap->SetName( aName );
+
+ return !aName.isEmpty();
+}
+
+bool SfxHTMLParser::ParseAreaOptions(ImageMap * pImageMap, std::u16string_view rBaseURL,
+ const HTMLOptions& rOptions,
+ SvMacroItemId nEventMouseOver,
+ SvMacroItemId nEventMouseOut )
+{
+ DBG_ASSERT( pImageMap, "ParseAreaOptions: no Image-Map" );
+
+ IMapObjectType nShape = IMapObjectType::Rectangle;
+ std::vector<sal_uInt32> aCoords;
+ OUString aName, aHRef, aAlt, aTarget;
+ bool bNoHRef = false;
+ SvxMacroTableDtor aMacroTbl;
+
+ for (size_t i = rOptions.size(); i; )
+ {
+ SvMacroItemId nEvent = SvMacroItemId::NONE;
+ ScriptType eScrpType = STARBASIC;
+ const HTMLOption& rOption = rOptions[--i];
+ switch( rOption.GetToken() )
+ {
+ case HtmlOptionId::NAME:
+ aName = rOption.GetString();
+ break;
+ case HtmlOptionId::SHAPE:
+ rOption.GetEnum( nShape, aAreaShapeOptEnums );
+ break;
+ case HtmlOptionId::COORDS:
+ rOption.GetNumbers( aCoords );
+ break;
+ case HtmlOptionId::HREF:
+ aHRef = INetURLObject::GetAbsURL( rBaseURL, rOption.GetString() );
+ break;
+ case HtmlOptionId::NOHREF:
+ bNoHRef = true;
+ break;
+ case HtmlOptionId::ALT:
+ aAlt = rOption.GetString();
+ break;
+ case HtmlOptionId::TARGET:
+ aTarget = rOption.GetString();
+ break;
+
+ case HtmlOptionId::ONMOUSEOVER:
+ eScrpType = JAVASCRIPT;
+ [[fallthrough]];
+ case HtmlOptionId::SDONMOUSEOVER:
+ nEvent = nEventMouseOver;
+ goto IMAPOBJ_SETEVENT;
+
+ case HtmlOptionId::ONMOUSEOUT:
+ eScrpType = JAVASCRIPT;
+ [[fallthrough]];
+ case HtmlOptionId::SDONMOUSEOUT:
+ nEvent = nEventMouseOut;
+ goto IMAPOBJ_SETEVENT;
+IMAPOBJ_SETEVENT:
+ if( nEvent != SvMacroItemId::NONE)
+ {
+ OUString sTmp( rOption.GetString() );
+ if( !sTmp.isEmpty() )
+ {
+ sTmp = convertLineEnd(sTmp, GetSystemLineEnd());
+ aMacroTbl.Insert( nEvent, SvxMacro( sTmp, "", eScrpType ));
+ }
+ }
+ break;
+ default: break;
+ }
+ }
+
+ if( bNoHRef )
+ aHRef.clear();
+
+ bool bNewArea = true;
+ switch( nShape )
+ {
+ case IMapObjectType::Rectangle:
+ if( aCoords.size() >=4 )
+ {
+ tools::Rectangle aRect( aCoords[0], aCoords[1],
+ aCoords[2], aCoords[3] );
+ std::unique_ptr<IMapRectangleObject> pMapRObj( new IMapRectangleObject(aRect, aHRef, aAlt, OUString(), aTarget, aName,
+ !bNoHRef ));
+ if( !aMacroTbl.empty() )
+ pMapRObj->SetMacroTable( aMacroTbl );
+ pImageMap->InsertIMapObject( std::move(pMapRObj) );
+ }
+ break;
+ case IMapObjectType::Circle:
+ if( aCoords.size() >=3 )
+ {
+ Point aPoint( aCoords[0], aCoords[1] );
+ std::unique_ptr<IMapCircleObject> pMapCObj(new IMapCircleObject(aPoint, aCoords[2],aHRef, aAlt, OUString(),
+ aTarget, aName, !bNoHRef ));
+ if( !aMacroTbl.empty() )
+ pMapCObj->SetMacroTable( aMacroTbl );
+ pImageMap->InsertIMapObject( std::move(pMapCObj) );
+ }
+ break;
+ case IMapObjectType::Polygon:
+ if( aCoords.size() >=6 )
+ {
+ sal_uInt16 nCount = aCoords.size() / 2;
+ tools::Polygon aPoly( nCount );
+ for( sal_uInt16 i=0; i<nCount; i++ )
+ aPoly[i] = Point( aCoords[2*i], aCoords[2*i+1] );
+ std::unique_ptr<IMapPolygonObject> pMapPObj(new IMapPolygonObject( aPoly, aHRef, aAlt, OUString(), aTarget, aName,
+ !bNoHRef ));
+ if( !aMacroTbl.empty() )
+ pMapPObj->SetMacroTable( aMacroTbl );
+ pImageMap->InsertIMapObject( std::move(pMapPObj) );
+ }
+ break;
+ default:
+ bNewArea = false;
+ }
+
+ return bNewArea;
+}
+
+void SfxHTMLParser::StartFileDownload(const OUString& rURL)
+{
+ DBG_ASSERT( !pDLMedium, "StartFileDownload when active Download" );
+ if( pDLMedium )
+ return;
+
+ pDLMedium.reset( new SfxMedium( rURL, SFX_STREAM_READONLY ) );
+ pDLMedium->Download();
+}
+
+bool SfxHTMLParser::FinishFileDownload( OUString& rStr )
+{
+ bool bOK = pDLMedium && pDLMedium->GetErrorCode() == ERRCODE_NONE;
+ if( bOK )
+ {
+ SvStream* pStream = pDLMedium->GetInStream();
+ DBG_ASSERT( pStream, "No In-Stream received from Medium" );
+
+ SvMemoryStream aStream;
+ if( pStream )
+ aStream.WriteStream( *pStream );
+
+ sal_uInt64 const nLen = aStream.TellEnd();
+ aStream.Seek( 0 );
+ rStr = read_uInt8s_ToOUString(aStream, nLen, RTL_TEXTENCODING_UTF8);
+ }
+
+ pDLMedium.reset();
+
+ return bOK;
+}
+
+void SfxHTMLParser::GetScriptType_Impl( SvKeyValueIterator *pHTTPHeader )
+{
+ aScriptType = SVX_MACRO_LANGUAGE_JAVASCRIPT;
+ eScriptType = JAVASCRIPT;
+ if( !pHTTPHeader )
+ return;
+
+ SvKeyValue aKV;
+ for( bool bCont = pHTTPHeader->GetFirst( aKV ); bCont;
+ bCont = pHTTPHeader->GetNext( aKV ) )
+ {
+ if( aKV.GetKey().equalsIgnoreAsciiCase(
+ OOO_STRING_SVTOOLS_HTML_META_content_script_type ) )
+ {
+ if( !aKV.GetValue().isEmpty() )
+ {
+ OUString aTmp( aKV.GetValue() );
+ if( aTmp.startsWithIgnoreAsciiCase( "text/" ) )
+ aTmp = aTmp.copy( 5 );
+ else if( aTmp.startsWithIgnoreAsciiCase( "application/" ) )
+ aTmp = aTmp.copy( 12 );
+ else
+ break;
+
+ if( aTmp.startsWithIgnoreAsciiCase( "x-" ) ) // MIME-experimental
+ {
+ aTmp = aTmp.copy( 2 );
+ }
+
+ if( aTmp.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_LG_starbasic ) )
+ {
+ eScriptType = STARBASIC;
+ aScriptType = SVX_MACRO_LANGUAGE_STARBASIC;
+ }
+ if( !aTmp.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_LG_javascript ) )
+ {
+ eScriptType = EXTENDED_STYPE;
+ aScriptType = aTmp;
+ }
+ }
+ break;
+ }
+ }
+}
+
+ScriptType SfxHTMLParser::GetScriptType( SvKeyValueIterator *pHTTPHeader ) const
+{
+ if( aScriptType.isEmpty() )
+ const_cast<SfxHTMLParser *>(this)->GetScriptType_Impl( pHTTPHeader );
+
+ return eScriptType;
+}
+
+const OUString& SfxHTMLParser::GetScriptTypeString(
+ SvKeyValueIterator *pHTTPHeader ) const
+{
+ if( aScriptType.isEmpty() )
+ const_cast<SfxHTMLParser *>(this)->GetScriptType_Impl( pHTTPHeader );
+
+ return aScriptType;
+}
+
+double SfxHTMLParser::GetTableDataOptionsValNum( sal_uInt32& nNumForm,
+ LanguageType& eNumLang, const OUString& aValStr, std::u16string_view aNumStr,
+ SvNumberFormatter& rFormatter )
+{
+ LanguageType eParseLang(o3tl::toInt32(aNumStr));
+ sal_uInt32 nParseForm = rFormatter.GetFormatForLanguageIfBuiltIn( 0, eParseLang );
+ double fVal;
+ (void)rFormatter.IsNumberFormat(aValStr, nParseForm, fVal);
+ if ( comphelper::string::getTokenCount(aNumStr, ';') > 2 )
+ {
+ sal_Int32 nIdx {0};
+ eNumLang = LanguageType(o3tl::toInt32(o3tl::getToken(aNumStr, 1, ';', nIdx )));
+ OUString aFormat( aNumStr.substr( nIdx ) );
+ sal_Int32 nCheckPos;
+ SvNumFormatType nType;
+ if ( eNumLang != LANGUAGE_SYSTEM )
+ rFormatter.PutEntry( aFormat, nCheckPos, nType, nNumForm, eNumLang );
+ else
+ rFormatter.PutandConvertEntry( aFormat, nCheckPos, nType, nNumForm,
+ eParseLang, eNumLang, true);
+ }
+ else
+ {
+ eNumLang = LANGUAGE_SYSTEM;
+ nNumForm = rFormatter.GetFormatForLanguageIfBuiltIn( 0, eNumLang );
+ }
+ return fVal;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sfx2/source/bastyp/sfxresid.cxx b/sfx2/source/bastyp/sfxresid.cxx
new file mode 100644
index 000000000..1bc6d68bb
--- /dev/null
+++ b/sfx2/source/bastyp/sfxresid.cxx
@@ -0,0 +1,24 @@
+/* -*- 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 <sfx2/sfxresid.hxx>
+
+OUString SfxResId(TranslateId aId) { return Translate::get(aId, Translate::Create("sfx")); }
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */