diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /sfx2/source/bastyp | |
parent | Initial commit. (diff) | |
download | libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | sfx2/source/bastyp/bitset.cxx | 108 | ||||
-rw-r--r-- | sfx2/source/bastyp/fltfnc.cxx | 1111 | ||||
-rw-r--r-- | sfx2/source/bastyp/fltlst.cxx | 118 | ||||
-rw-r--r-- | sfx2/source/bastyp/fltlst.hxx | 50 | ||||
-rw-r--r-- | sfx2/source/bastyp/frmhtml.cxx | 101 | ||||
-rw-r--r-- | sfx2/source/bastyp/frmhtmlw.cxx | 294 | ||||
-rw-r--r-- | sfx2/source/bastyp/helper.cxx | 229 | ||||
-rw-r--r-- | sfx2/source/bastyp/mieclip.cxx | 103 | ||||
-rw-r--r-- | sfx2/source/bastyp/progress.cxx | 401 | ||||
-rw-r--r-- | sfx2/source/bastyp/sfxhtml.cxx | 345 | ||||
-rw-r--r-- | sfx2/source/bastyp/sfxresid.cxx | 24 |
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: */ |