From 940b4d1848e8c70ab7642901a68594e8016caffc Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 27 Apr 2024 18:51:28 +0200 Subject: Adding upstream version 1:7.0.4. Signed-off-by: Daniel Baumann --- sfx2/source/bastyp/bitset.cxx | 108 ++++ sfx2/source/bastyp/fltfnc.cxx | 1122 +++++++++++++++++++++++++++++++++++++++ sfx2/source/bastyp/fltlst.cxx | 118 ++++ sfx2/source/bastyp/fltlst.hxx | 50 ++ sfx2/source/bastyp/frmhtml.cxx | 101 ++++ sfx2/source/bastyp/frmhtmlw.cxx | 306 +++++++++++ sfx2/source/bastyp/helper.cxx | 235 ++++++++ sfx2/source/bastyp/mieclip.cxx | 100 ++++ sfx2/source/bastyp/progress.cxx | 401 ++++++++++++++ sfx2/source/bastyp/sfxhtml.cxx | 343 ++++++++++++ sfx2/source/bastyp/sfxresid.cxx | 28 + 11 files changed, 2912 insertions(+) create mode 100644 sfx2/source/bastyp/bitset.cxx create mode 100644 sfx2/source/bastyp/fltfnc.cxx create mode 100644 sfx2/source/bastyp/fltlst.cxx create mode 100644 sfx2/source/bastyp/fltlst.hxx create mode 100644 sfx2/source/bastyp/frmhtml.cxx create mode 100644 sfx2/source/bastyp/frmhtmlw.cxx create mode 100644 sfx2/source/bastyp/helper.cxx create mode 100644 sfx2/source/bastyp/mieclip.cxx create mode 100644 sfx2/source/bastyp/progress.cxx create mode 100644 sfx2/source/bastyp/sfxhtml.cxx create mode 100644 sfx2/source/bastyp/sfxresid.cxx (limited to 'sfx2/source/bastyp') diff --git a/sfx2/source/bastyp/bitset.cxx b/sfx2/source/bastyp/bitset.cxx new file mode 100644 index 000000000..9dc18f3e5 --- /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 +#include + +#include + +#include + +// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include "fltlst.hxx" +#include + +#include +#include + +#if defined(DBG_UTIL) +unsigned SfxStack::nLevel = 0; +#endif + +using namespace com::sun::star; + +namespace +{ + class theSfxFilterListener : public rtl::Static {}; + class SfxFilterArray + { + SfxFilterList_Impl aList; + public: + + SfxFilterList_Impl& getList() + { + return aList; + } + }; + class theSfxFilterArray : public rtl::Static {}; +} + +static SfxFilterList_Impl* pFilterArr = nullptr; +static bool bFirstRead = true; + +static void CreateFilterArr() +{ + pFilterArr = &theSfxFilterArray::get().getList(); + theSfxFilterListener::get(); +} + +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 SfxFilterContainer::GetFilter4EA(const OUString& rEA, SfxFilterFlags nMust, SfxFilterFlags nDont) const +{ + SfxFilterMatcher aMatch(pImpl->aName); + return aMatch.GetFilter4EA(rEA, nMust, nDont); +} + +std::shared_ptr SfxFilterContainer::GetFilter4Extension(const OUString& rExt, SfxFilterFlags nMust, SfxFilterFlags nDont) const +{ + SfxFilterMatcher aMatch(pImpl->aName); + return aMatch.GetFilter4Extension(rExt, nMust, nDont); +} + +std::shared_ptr SfxFilterContainer::GetFilter4FilterName(const OUString& rName, SfxFilterFlags nMust, SfxFilterFlags nDont) const +{ + SfxFilterMatcher aMatch(pImpl->aName); + return aMatch.GetFilter4FilterName(rName, nMust, nDont); +} + +std::shared_ptr 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 SfxFilterContainer::GetDefaultFilter_Impl( const OUString& 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 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& 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 +{ + static std::vector > aImplArr; + static 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& aImpl : aImplArr) + if (aImpl->aName == aName) + return *aImpl; + + // first Matcher created for this factory + aImplArr.push_back(std::make_unique(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& 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 SfxFilterMatcher::GetAnyFilter( SfxFilterFlags nMust, SfxFilterFlags nDont ) const +{ + m_rImpl.InitForIterating(); + for (const std::shared_ptr& 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& rpFilter ) const +{ + uno::Reference 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& rpFilter, SfxFilterFlags nMust, SfxFilterFlags nDont ) const +{ + return GuessFilterControlDefaultUI( rMedium, rpFilter, nMust, nDont ); +} + + +ErrCode SfxFilterMatcher::GuessFilterControlDefaultUI( SfxMedium& rMedium, std::shared_ptr& rpFilter, SfxFilterFlags nMust, SfxFilterFlags nDont ) const +{ + std::shared_ptr pOldFilter = rpFilter; + + // no detection service -> nothing to do ! + uno::Reference xDetection( + comphelper::getProcessServiceFactory()->createInstance("com.sun.star.document.TypeDetection"), uno::UNO_QUERY); + + if (!xDetection.is()) + return ERRCODE_ABORT; + + OUString sTypeName; + 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; + + // 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( + 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(); + } + } + // no stream exists => try flat detection without preselection as fallback + else + sTypeName = xDetection->queryTypeByURL(sURL); + + if (!sTypeName.isEmpty()) + { + std::shared_ptr 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::makeAny(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& 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 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 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 xInfoBox(Application::CreateMessageDialog(nullptr, + VclMessageType::Info, VclButtonsType::Ok, + aText)); + xInfoBox->run(); + return false; + } + else + return true; +} + + +ErrCode SfxFilterMatcher::DetectFilter( SfxMedium& rMedium, std::shared_ptr& rpFilter ) const +/* [Description] + + Here the Filter selection box is pulled up. Otherwise GuessFilter + */ + +{ + std::shared_ptr pOldFilter = rMedium.GetFilter(); + if ( pOldFilter ) + { + if( !IsFilterInstalled_Impl( pOldFilter ) ) + pOldFilter = nullptr; + else + { + const SfxStringItem* pSalvageItem = SfxItemSet::GetItem(rMedium.GetItemSet(), SID_DOC_SALVAGE, false); + if ( ( pOldFilter->GetFilterFlags() & SfxFilterFlags::PACKED ) && pSalvageItem ) + // Salvage is always done without packing + pOldFilter = nullptr; + } + } + + std::shared_ptr pFilter = pOldFilter; + + bool bPreview = rMedium.IsPreview_Impl(); + const SfxStringItem* pReferer = SfxItemSet::GetItem(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 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(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 SfxFilterMatcher::GetFilterForProps( const css::uno::Sequence < beans::NamedValue >& aSeq, SfxFilterFlags nMust, SfxFilterFlags nDont ) const +{ + uno::Reference< lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory(); + uno::Reference< container::XContainerQuery > xTypeCFG; + if( xServiceManager.is() ) + xTypeCFG.set( xServiceManager->createInstance( "com.sun.star.document.TypeDetection" ), uno::UNO_QUERY ); + if ( xTypeCFG.is() ) + { + // make query for all types matching the properties + uno::Reference < css::container::XEnumeration > xEnum = xTypeCFG->createSubSetEnumerationByProperties( aSeq ); + while ( xEnum->hasMoreElements() ) + { + ::comphelper::SequenceAsHashMap aProps( xEnum->nextElement() ); + OUString aValue; + + // try to get the preferred filter (works without loading all filters!) + if ( (aProps[OUString("PreferredFilter")] >>= aValue) && !aValue.isEmpty() ) + { + std::shared_ptr 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(); + aProps[OUString("Name")] >>= aValue; + pFilter = GetFilter4EA( aValue, nMust, nDont ); + if ( pFilter ) + return pFilter; + } + else + return pFilter; + } + else + return pFilter; + } + } + } + + return nullptr; +} + +std::shared_ptr SfxFilterMatcher::GetFilter4Mime( const OUString& rMediaType, SfxFilterFlags nMust, SfxFilterFlags nDont ) const +{ + if ( m_rImpl.pList ) + { + for (const std::shared_ptr& 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::makeAny(rMediaType) } }; + return GetFilterForProps( aSeq, nMust, nDont ); +} + +std::shared_ptr SfxFilterMatcher::GetFilter4EA( const OUString& rType, SfxFilterFlags nMust, SfxFilterFlags nDont ) const +{ + if ( m_rImpl.pList ) + { + std::shared_ptr pFirst; + for (const std::shared_ptr& 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::makeAny(rType) } }; + return GetFilterForProps( aSeq, nMust, nDont ); +} + +std::shared_ptr SfxFilterMatcher::GetFilter4Extension( const OUString& rExt, SfxFilterFlags nMust, SfxFilterFlags nDont ) const +{ + if ( m_rImpl.pList ) + { + for (const std::shared_ptr& pFilter : *m_rImpl.pList) + { + SfxFilterFlags nFlags = pFilter->GetFilterFlags(); + if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) ) + { + OUString sWildCard = ToUpper_Impl( pFilter->GetWildcard().getGlob() ); + OUString sExt = ToUpper_Impl( rExt ); + + if (sExt.isEmpty()) + continue; + + if (sExt[0] != '.') + sExt = "." + sExt; + + 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::makeAny(uno::Sequence < OUString > { sExt } ) } }; + return GetFilterForProps( aSeq, nMust, nDont ); +} + +std::shared_ptr 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::makeAny(SotExchange::GetFormatName( nId )) } }; + return GetFilterForProps( aSeq, nMust, nDont ); +} + +std::shared_ptr SfxFilterMatcher::GetFilter4UIName( const OUString& rName, SfxFilterFlags nMust, SfxFilterFlags nDont ) const +{ + m_rImpl.InitForIterating(); + std::shared_ptr pFirstFilter; + for (const std::shared_ptr& 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 SfxFilterMatcher::GetFilter4FilterName( const OUString& rName, SfxFilterFlags nMust, SfxFilterFlags nDont ) const +{ + OUString aName( rName ); + sal_Int32 nIndex = aName.indexOf(": "); + if ( nIndex != -1 ) + { + SAL_WARN( "sfx.bastyp", "Old filter name used!"); + aName = rName.copy( nIndex + 2 ); + } + + if ( bFirstRead ) + { + 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() ) + { + if ( !pFilterArr ) + CreateFilterArr(); + else + { + for (const std::shared_ptr& 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& 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 pFilter = GetFilter4Extension( *pString ); + return pFilter && + !pFilter->GetWildcard().Matches("") && + !pFilter->GetWildcard().Matches("*.*") && + !pFilter->GetWildcard().Matches("*"); +} + + +SfxFilterMatcherIter::SfxFilterMatcherIter( + const SfxFilterMatcher& rMatcher, + SfxFilterFlags nOrMaskP, SfxFilterFlags nAndMaskP ) + : nOrMask( nOrMaskP ), nAndMask( nAndMaskP ), + nCurrent(0), m_rMatch(rMatcher.m_rImpl) +{ + if( nOrMask == static_cast(0xffff) ) //Due to faulty build on s + nOrMask = SfxFilterFlags::NONE; + m_rMatch.InitForIterating(); +} + + +std::shared_ptr SfxFilterMatcherIter::Find_Impl() +{ + std::shared_ptr 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 SfxFilterMatcherIter::First() +{ + nCurrent = 0; + return Find_Impl(); +} + + +std::shared_ptr 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, + const OUString& sPrefix ) +{ + OUStringBuffer sString ( 1000 ) ; + sal_Int32 nCount = lList.getLength(); + sal_Int32 nItem = 0 ; + for( nItem=0; nItem& 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 sPattern ; + 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::mask) == 0); + nFlags = static_cast(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, ',', OUString() ); + } + 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, ';', "*." ); + } + } + else if ( rTypeProperty.Name == "URLPattern" ) + { + uno::Sequence< OUString > lPattern; + rTypeProperty.Value >>= lPattern; + sPattern = implc_convertStringlistToString( lPattern, ';', OUString() ); + } + } + } + } + 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 pFilter = bUpdate ? SfxFilter::GetFilterByName( sFilterName ) : nullptr; + if (!pFilter) + { + pFilter = std::make_shared( sFilterName , + sExtension , + nFlags , + nClipboardId , + sType , + sMimeType , + sUserData , + sServiceName , + bEnabled ); + rList.push_back( pFilter ); + } + else + { + SfxFilter* pFilt = const_cast(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(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& pFilter : rList) + { + SfxFilter* pNonConstFilter = const_cast(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 +#include + +#include + +#include +#include + + +// namespaces + +using namespace ::com::sun::star; + +namespace { + +class SfxRefreshListener : public ::cppu::WeakImplHelper +{ + 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 +#include +#include +#include + +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..a86a88c70 --- /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 + +#include +#include + +static char const sHTML_SC_yes[] = "YES"; +static char const sHTML_SC_no[] = "NO"; +static char const sHTML_SC_auto[] = "AUTO"; + +static HTMLOptionEnum 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, const OUString& 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..007a9c89a --- /dev/null +++ b/sfx2/source/bastyp/frmhtmlw.cxx @@ -0,0 +1,306 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + +using namespace ::com::sun::star; + +static char const sHTML_SC_yes[] = "YES"; +static char const sHTML_SC_no[] = "NO"; + +void SfxFrameHTMLWriter::OutMeta( SvStream& rStrm, + const char *pIndent, + const OUString& rName, + const OUString& rContent, + bool bHTTPEquiv, + rtl_TextEncoding eDestEnc, + OUString *pNonConvertableChars ) +{ + rStrm.WriteCharPtr( SAL_NEWLINE_STRING ); + if( pIndent ) + rStrm.WriteCharPtr( pIndent ); + + OStringBuffer sOut; + sOut.append('<').append(OOO_STRING_SVTOOLS_HTML_meta).append(' ') + .append(bHTTPEquiv ? OOO_STRING_SVTOOLS_HTML_O_httpequiv : OOO_STRING_SVTOOLS_HTML_O_name).append("=\""); + rStrm.WriteOString( sOut.makeStringAndClear() ); + + HTMLOutFuncs::Out_String( rStrm, rName, eDestEnc, pNonConvertableChars ); + + sOut.append("\" ").append(OOO_STRING_SVTOOLS_HTML_O_content).append("=\""); + rStrm.WriteOString( sOut.makeStringAndClear() ); + + HTMLOutFuncs::Out_String( rStrm, rContent, eDestEnc, pNonConvertableChars ).WriteCharPtr( "\"/>" ); +} + +void SfxFrameHTMLWriter::Out_DocInfo( SvStream& rStrm, const OUString& rBaseURL, + const uno::Reference & i_xDocProps, + const char *pIndent, + rtl_TextEncoding eDestEnc, + OUString *pNonConvertableChars ) +{ + const char *pCharSet = + rtl_getBestMimeCharsetFromTextEncoding( eDestEnc ); + + if( pCharSet ) + { + OUString aContentType = "text/html; charset=" + OUString(pCharSet, strlen(pCharSet), RTL_TEXTENCODING_UTF8); + OutMeta( rStrm, pIndent, OOO_STRING_SVTOOLS_HTML_META_content_type, aContentType, true, + eDestEnc, 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, eDestEnc, 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 ); + + OString sOut = "<" OOO_STRING_SVTOOLS_HTML_base " " + OOO_STRING_SVTOOLS_HTML_O_target "=\""; + rStrm.WriteOString( sOut ); + HTMLOutFuncs::Out_String( rStrm, rTarget, eDestEnc, 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, eDestEnc, 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, + eDestEnc, pNonConvertableChars ); + } + + // Author + const OUString& rAuthor = i_xDocProps->getAuthor(); + if( !rAuthor.isEmpty() ) + OutMeta( rStrm, pIndent, OOO_STRING_SVTOOLS_HTML_META_author, rAuthor, false, + eDestEnc, 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, + eDestEnc, pNonConvertableChars ); + + // changedby + const OUString& rChangedBy = i_xDocProps->getModifiedBy(); + if( !rChangedBy.isEmpty() ) + OutMeta( rStrm, pIndent, OOO_STRING_SVTOOLS_HTML_META_changedby, rChangedBy, false, + eDestEnc, pNonConvertableChars ); + + // changed + uDT = i_xDocProps->getModificationDate(); + ::sax::Converter::convertTimeOrDateTime(aBuffer, uDT); + + OutMeta( rStrm, pIndent, OOO_STRING_SVTOOLS_HTML_META_changed, aBuffer.makeStringAndClear(), false, + eDestEnc, pNonConvertableChars ); + + // Subject + const OUString& rTheme = i_xDocProps->getSubject(); + if( !rTheme.isEmpty() ) + OutMeta( rStrm, pIndent, OOO_STRING_SVTOOLS_HTML_META_classification, rTheme, false, + eDestEnc, pNonConvertableChars ); + + // Description + const OUString& rComment = i_xDocProps->getDescription(); + if( !rComment.isEmpty() ) + OutMeta( rStrm, pIndent, OOO_STRING_SVTOOLS_HTML_META_description, rComment, false, + eDestEnc, pNonConvertableChars); + + // Keywords + OUString Keywords = ::comphelper::string::convertCommaSeparated( + i_xDocProps->getKeywords()); + if( !Keywords.isEmpty() ) + OutMeta( rStrm, pIndent, OOO_STRING_SVTOOLS_HTML_META_keywords, Keywords, false, + eDestEnc, pNonConvertableChars); + + uno::Reference < script::XTypeConverter > xConverter( script::Converter::create( + ::comphelper::getProcessComponentContext() ) ); + uno::Reference xUserDefinedProps( + i_xDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW); + uno::Reference xPropInfo = + xUserDefinedProps->getPropertySetInfo(); + DBG_ASSERT(xPropInfo.is(), "UserDefinedProperties Info is null"); + const uno::Sequence 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, + eDestEnc, 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, + rtl_TextEncoding eDestEnc, 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(' ').append(OOO_STRING_SVTOOLS_HTML_O_src) + .append("=\""); + rOut.WriteOString( sOut.makeStringAndClear() ); + HTMLOutFuncs::Out_String( rOut, aURL, eDestEnc, pNonConvertableChars ); + sOut.append('\"'); + } + } + + aAny = xSet->getPropertyValue("FrameName"); + if ( (aAny >>= aStr) && !aStr.isEmpty() ) + { + sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_name) + .append("=\""); + rOut.WriteOString( sOut.makeStringAndClear() ); + HTMLOutFuncs::Out_String( rOut, aStr, eDestEnc, 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(' ').append(OOO_STRING_SVTOOLS_HTML_O_scrolling) + .append(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..a6bb0d052 --- /dev/null +++ b/sfx2/source/bastyp/helper.cxx @@ -0,0 +1,235 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace com::sun::star; +using namespace comphelper; +using namespace osl; + +using ::std::vector; + + +std::vector SfxContentHelper::GetResultSet( const OUString& rURL ) +{ + vector aList; + try + { + ::ucbhelper::Content aCnt( rURL, uno::Reference< ucb::XCommandEnvironment >(), comphelper::getProcessComponentContext() ); + uno::Reference< sdbc::XResultSet > xResultSet; + uno::Reference< ucb::XDynamicResultSet > xDynResultSet; + uno::Sequence< OUString > aProps(3); + OUString* pProps = aProps.getArray(); + pProps[0] = "Title"; + pProps[1] = "ContentType"; + pProps[2] = "IsFolder"; + + try + { + xDynResultSet = aCnt.createDynamicCursor( aProps ); + 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; + uno::Sequence< OUString > aProps(2); + OUString* pProps = aProps.getArray(); + pProps[0] = "Title"; + pProps[1] = "IsFolder"; + + try + { + uno::Reference< ucb::XDynamicResultSet > xDynResultSet = aCnt.createDynamicCursor( aProps ); + 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 ? OUStringLiteral("1") : OUStringLiteral("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(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( const OUString& 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( const OUString& 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..83920a175 --- /dev/null +++ b/sfx2/source/bastyp/mieclip.cxx @@ -0,0 +1,100 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include + +#include + +MSE40HTMLClipFormatObj::~MSE40HTMLClipFormatObj() +{ +} + +SvStream* MSE40HTMLClipFormatObj::IsValid( SvStream& rStream ) +{ + bool bRet = false; + pStrm.reset(); + + OString 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 ) && + sLine.getToken( 0, ':', nIndex ) == "Version" ) + { + while( rStream.ReadLine( sLine ) ) + { + nIndex = 0; + OString sTmp(sLine.getToken(0, ':', nIndex)); + if (sTmp == "StartHTML") + nStt = sLine.copy(nIndex).toInt32(); + else if (sTmp == "EndHTML") + nEnd = sLine.copy(nIndex).toInt32(); + else if (sTmp == "StartFragment") + nFragStart = sLine.copy(nIndex).toInt32(); + else if (sTmp == "EndFragment") + nFragEnd = sLine.copy(nIndex).toInt32(); + else if (sTmp == "SourceURL") + sBaseURL = OStringToOUString( sLine.copy(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 +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 . +*/ + +{ + 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(pMedium->GetItemSet(), SID_HIDDEN, false); + if ( !pHiddenItem || !pHiddenItem->GetValue() ) + { + const SfxUnoAnyItem* pIndicatorItem = SfxItemSet::GetItem(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] + + +*/ + +{ + 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] + + +*/ + +{ + 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 , which should be + queried after a current , + 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 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] + + + +*/ + +{ + 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..334a62c26 --- /dev/null +++ b/sfx2/source/bastyp/sfxhtml.cxx @@ -0,0 +1,343 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + + +using namespace ::com::sun::star; + + +// +static HTMLOptionEnum const aAreaShapeOptEnums[] = +{ + { OOO_STRING_SVTOOLS_HTML_SH_rect, IMAP_OBJ_RECTANGLE }, + { OOO_STRING_SVTOOLS_HTML_SH_rectangle, IMAP_OBJ_RECTANGLE }, + { OOO_STRING_SVTOOLS_HTML_SH_circ, IMAP_OBJ_CIRCLE }, + { OOO_STRING_SVTOOLS_HTML_SH_circle, IMAP_OBJ_CIRCLE }, + { OOO_STRING_SVTOOLS_HTML_SH_poly, IMAP_OBJ_POLYGON }, + { OOO_STRING_SVTOOLS_HTML_SH_polygon, IMAP_OBJ_POLYGON }, + { nullptr, 0 } +}; + +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, const OUString& rBaseURL, + const HTMLOptions& rOptions, + SvMacroItemId nEventMouseOver, + SvMacroItemId nEventMouseOut ) +{ + DBG_ASSERT( pImageMap, "ParseAreaOptions: no Image-Map" ); + + sal_uInt16 nShape = IMAP_OBJ_RECTANGLE; + std::vector 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 IMAP_OBJ_RECTANGLE: + if( aCoords.size() >=4 ) + { + tools::Rectangle aRect( aCoords[0], aCoords[1], + aCoords[2], aCoords[3] ); + std::unique_ptr pMapRObj( new IMapRectangleObject(aRect, aHRef, aAlt, OUString(), aTarget, aName, + !bNoHRef )); + if( !aMacroTbl.empty() ) + pMapRObj->SetMacroTable( aMacroTbl ); + pImageMap->InsertIMapObject( std::move(pMapRObj) ); + } + break; + case IMAP_OBJ_CIRCLE: + if( aCoords.size() >=3 ) + { + Point aPoint( aCoords[0], aCoords[1] ); + std::unique_ptr 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 IMAP_OBJ_POLYGON: + if( aCoords.size() >=6 ) + { + sal_uInt16 nCount = aCoords.size() / 2; + tools::Polygon aPoly( nCount ); + for( sal_uInt16 i=0; i 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(this)->GetScriptType_Impl( pHTTPHeader ); + + return eScriptType; +} + +const OUString& SfxHTMLParser::GetScriptTypeString( + SvKeyValueIterator *pHTTPHeader ) const +{ + if( aScriptType.isEmpty() ) + const_cast(this)->GetScriptType_Impl( pHTTPHeader ); + + return aScriptType; +} + +double SfxHTMLParser::GetTableDataOptionsValNum( sal_uInt32& nNumForm, + LanguageType& eNumLang, const OUString& aValStr, const OUString& aNumStr, + SvNumberFormatter& rFormatter ) +{ + LanguageType eParseLang(aNumStr.toInt32()); + 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(aNumStr.getToken( 1, ';', nIdx ).toInt32()); + OUString aFormat( aNumStr.copy( 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..250494d52 --- /dev/null +++ b/sfx2/source/bastyp/sfxresid.cxx @@ -0,0 +1,28 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +OUString SfxResId(const char* pId) +{ + return Translate::get(pId, Translate::Create("sfx")); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit v1.2.3