Version 3.6.0.4, tag libreoffice-3.6.0.4
[LibreOffice.git] / sfx2 / source / bastyp / fltfnc.cxx
blob72b35900575e8c4528c9ef38415cf5aeadc3d21d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include "fltfnc.hxx"
31 #include <com/sun/star/uno/Exception.hpp>
32 #include <com/sun/star/beans/PropertyValue.hpp>
33 #include <com/sun/star/beans/NamedValue.hpp>
34 #include <com/sun/star/container/XNameAccess.hpp>
35 #include <com/sun/star/container/XEnumeration.hpp>
36 #include <com/sun/star/datatransfer/DataFlavor.hpp>
37 #include <com/sun/star/document/XTypeDetection.hpp>
38 #include <com/sun/star/container/XContainerQuery.hpp>
40 #include <comphelper/sequenceashashmap.hxx>
42 #include <sot/exchange.hxx>
43 #include <basic/sbmeth.hxx>
44 #include <basic/basmgr.hxx>
45 #include <basic/sbstar.hxx>
46 #include <basic/sbxobj.hxx>
47 #include <basic/sbxmeth.hxx>
48 #include <basic/sbxcore.hxx>
49 #include <vcl/msgbox.hxx>
50 #include <rtl/ustring.hxx>
51 #include <rtl/ustrbuf.hxx>
52 #include <svl/eitem.hxx>
53 #include <svl/intitem.hxx>
54 #include <svl/stritem.hxx>
55 #include <svl/lckbitem.hxx>
56 #include <svl/inettype.hxx>
57 #include <svl/rectitem.hxx>
59 #include <sot/storage.hxx>
60 #include <com/sun/star/frame/XDispatchProviderInterceptor.hpp>
61 #include <com/sun/star/frame/XDispatch.hpp>
62 #include <com/sun/star/frame/XDispatchProvider.hpp>
63 #include <com/sun/star/frame/XStatusListener.hpp>
64 #include <com/sun/star/frame/FrameSearchFlag.hpp>
65 #include <com/sun/star/frame/XDispatchProviderInterception.hpp>
66 #include <com/sun/star/frame/FeatureStateEvent.hpp>
67 #include <com/sun/star/frame/DispatchDescriptor.hpp>
68 #include <com/sun/star/frame/XController.hpp>
69 #include <com/sun/star/frame/XFrameActionListener.hpp>
70 #include <com/sun/star/frame/XComponentLoader.hpp>
71 #include <com/sun/star/frame/XFrame.hpp>
72 #include <com/sun/star/frame/FrameActionEvent.hpp>
73 #include <com/sun/star/frame/FrameAction.hpp>
74 #include <com/sun/star/frame/XFrameLoader.hpp>
75 #include <com/sun/star/frame/XLoadEventListener.hpp>
76 #include <com/sun/star/frame/XFilterDetect.hpp>
77 #include <com/sun/star/loader/XImplementationLoader.hpp>
78 #include <com/sun/star/loader/CannotActivateFactoryException.hpp>
79 #include <comphelper/processfactory.hxx>
81 #include <sal/types.h>
82 #include <com/sun/star/uno/Reference.hxx>
83 #include <com/sun/star/ucb/XContent.hpp>
84 #include <unotools/pathoptions.hxx>
85 #include <unotools/moduleoptions.hxx>
86 #include <comphelper/mediadescriptor.hxx>
87 #include <tools/urlobj.hxx>
89 #include <rtl/logfile.hxx>
90 #include <rtl/instance.hxx>
92 using namespace ::com::sun::star::uno;
93 using namespace ::com::sun::star::ucb;
94 using namespace ::com::sun::star::document;
95 using namespace ::com::sun::star::beans;
96 #include <svl/ctypeitm.hxx>
97 #include <svtools/sfxecode.hxx>
98 #include <unotools/syslocale.hxx>
100 #include "sfx2/sfxhelp.hxx"
101 #include <sfx2/docfilt.hxx>
102 #include <sfx2/docfac.hxx>
103 #include "sfxtypes.hxx"
104 #include <sfx2/sfxuno.hxx>
105 #include <sfx2/docfile.hxx>
106 #include <sfx2/progress.hxx>
107 #include "openflag.hxx"
108 #include "bastyp.hrc"
109 #include "sfx2/sfxresid.hxx"
110 #include <sfx2/doctempl.hxx>
111 #include <sfx2/frame.hxx>
112 #include <sfx2/dispatch.hxx>
113 #include <sfx2/viewfrm.hxx>
114 #include "helper.hxx"
115 #include "fltlst.hxx"
116 #include <sfx2/request.hxx>
117 #include "arrdecl.hxx"
118 #include <sfx2/appuno.hxx>
120 #include <boost/ptr_container/ptr_vector.hpp>
121 #include <functional>
123 namespace
125 class theSfxFilterListener : public rtl::Static<SfxFilterListener, theSfxFilterListener> {};
128 static SfxFilterList_Impl* pFilterArr = 0;
129 static sal_Bool bFirstRead = sal_True;
131 static void CreateFilterArr()
133 pFilterArr = new SfxFilterList_Impl;
134 theSfxFilterListener::get();
137 //----------------------------------------------------------------
138 inline String ToUpper_Impl( const String &rStr )
140 return SvtSysLocale().GetCharClass().uppercase( rStr );
143 //----------------------------------------------------------------
144 class SfxFilterContainer_Impl
146 public:
147 String aName;
148 String aServiceName;
150 SfxFilterContainer_Impl( const String& rName )
151 : aName( rName )
153 aServiceName = SfxObjectShell::GetServiceNameFromFactory( rName );
157 #define IMPL_FORWARD_LOOP( aMethod, ArgType, aArg ) \
158 const SfxFilter* SfxFilterContainer::aMethod( ArgType aArg, SfxFilterFlags nMust, SfxFilterFlags nDont ) const \
160 SfxFilterMatcher aMatch( pImpl->aName ); \
161 return aMatch.aMethod( aArg, nMust, nDont ); \
164 IMPL_FORWARD_LOOP( GetFilter4EA, const String&, rEA );
165 IMPL_FORWARD_LOOP( GetFilter4Extension, const String&, rExt );
166 IMPL_FORWARD_LOOP( GetFilter4FilterName, const String&, rName );
168 const SfxFilter* SfxFilterContainer::GetAnyFilter( SfxFilterFlags nMust, SfxFilterFlags nDont ) const
170 SfxFilterMatcher aMatch( pImpl->aName );
171 return aMatch.GetAnyFilter( nMust, nDont );
174 //----------------------------------------------------------------
176 SfxFilterContainer::SfxFilterContainer( const String& rName )
178 pImpl = new SfxFilterContainer_Impl( rName );
181 //----------------------------------------------------------------
183 SfxFilterContainer::~SfxFilterContainer()
185 delete pImpl;
188 //----------------------------------------------------------------
190 const String SfxFilterContainer::GetName() const
192 return pImpl->aName;
195 const SfxFilter* SfxFilterContainer::GetDefaultFilter_Impl( const String& rName )
197 // Try to find out the type of factory.
198 // Interpret given name as Service- and ShortName!
199 SvtModuleOptions aOpt;
200 SvtModuleOptions::EFactory eFactory = aOpt.ClassifyFactoryByServiceName(rName);
201 if (eFactory == SvtModuleOptions::E_UNKNOWN_FACTORY)
202 eFactory = aOpt.ClassifyFactoryByShortName(rName);
204 // could not classify factory by its service nor by its short name.
205 // Must be an unknown factory! => return NULL
206 if (eFactory == SvtModuleOptions::E_UNKNOWN_FACTORY)
207 return NULL;
209 // For the following code we need some additional informations.
210 String sServiceName = aOpt.GetFactoryName(eFactory);
211 String sShortName = aOpt.GetFactoryShortName(eFactory);
212 String sDefaultFilter = aOpt.GetFactoryDefaultFilter(eFactory);
214 // Try to get the default filter. Dont fiorget to verify it.
215 // May the set default filter does not exists any longer or
216 // does not fit the given factory.
217 const SfxFilterMatcher aMatcher;
218 const SfxFilter* pFilter = aMatcher.GetFilter4FilterName(sDefaultFilter);
220 if (
221 (pFilter) &&
222 (pFilter->GetServiceName().CompareIgnoreCaseToAscii( sServiceName ) != COMPARE_EQUAL)
225 pFilter = 0;
228 // If at least no default filter could be located - use any filter of this
229 // factory.
230 if (!pFilter)
232 if ( bFirstRead )
233 ReadFilters_Impl();
235 for ( size_t i = 0, n = pFilterArr->size(); i < n; ++i )
237 const SfxFilter* pCheckFilter = pFilterArr->at( i );
238 if ( pCheckFilter->GetServiceName().CompareIgnoreCaseToAscii( sServiceName ) == COMPARE_EQUAL )
240 pFilter = pCheckFilter;
241 break;
246 return pFilter;
250 //----------------------------------------------------------------
252 // Impl-Data is shared between all FilterMatchers of the same factory
253 class SfxFilterMatcher_Impl
255 public:
256 ::rtl::OUString aName;
257 SfxFilterList_Impl* pList; // is created on demand
259 void InitForIterating() const;
260 void Update();
261 SfxFilterMatcher_Impl(const ::rtl::OUString &rName)
262 : aName(rName)
263 , pList(0)
268 namespace
270 typedef boost::ptr_vector<SfxFilterMatcher_Impl> SfxFilterMatcherArr_Impl;
271 static SfxFilterMatcherArr_Impl aImplArr;
272 static int nSfxFilterMatcherCount;
274 class hasName :
275 public std::unary_function<SfxFilterMatcher_Impl, bool>
277 private:
278 const rtl::OUString& mrName;
279 public:
280 hasName(const rtl::OUString &rName) : mrName(rName) {}
281 bool operator() (const SfxFilterMatcher_Impl& rImpl) const
283 return rImpl.aName == mrName;
287 SfxFilterMatcher_Impl & getSfxFilterMatcher_Impl(const rtl::OUString &rName)
289 rtl::OUString aName;
291 if (!rName.isEmpty())
292 aName = SfxObjectShell::GetServiceNameFromFactory(rName);
294 // find the impl-Data of any comparable FilterMatcher that was created
295 // previously
296 SfxFilterMatcherArr_Impl::iterator aEnd = aImplArr.end();
297 SfxFilterMatcherArr_Impl::iterator aIter =
298 std::find_if(aImplArr.begin(), aEnd, hasName(rName));
299 if (aIter != aEnd)
300 return *aIter;
302 // first Matcher created for this factory
303 SfxFilterMatcher_Impl *pImpl = new SfxFilterMatcher_Impl(aName);
304 aImplArr.push_back(pImpl);
305 return *pImpl;
309 SfxFilterMatcher::SfxFilterMatcher( const String& rName )
310 : m_rImpl( getSfxFilterMatcher_Impl(rName) )
312 ++nSfxFilterMatcherCount;
315 SfxFilterMatcher::SfxFilterMatcher()
316 : m_rImpl( getSfxFilterMatcher_Impl(::rtl::OUString()) )
318 // global FilterMatcher always uses global filter array (also created on
319 // demand)
320 ++nSfxFilterMatcherCount;
323 SfxFilterMatcher::~SfxFilterMatcher()
325 --nSfxFilterMatcherCount;
326 if (nSfxFilterMatcherCount == 0)
327 aImplArr.clear();
330 void SfxFilterMatcher_Impl::Update()
332 if ( pList )
334 // this List was already used
335 pList->clear();
336 for ( size_t i = 0, n = pFilterArr->size(); i < n; ++i )
338 SfxFilter* pFilter = pFilterArr->at( i );
339 if ( pFilter->GetServiceName() == String(aName) )
340 pList->push_back( pFilter );
345 void SfxFilterMatcher_Impl::InitForIterating() const
347 if ( pList )
348 return;
350 if ( bFirstRead )
351 // global filter array has not been created yet
352 SfxFilterContainer::ReadFilters_Impl();
354 if ( !aName.isEmpty() )
356 // matcher of factory: use only filters of that document type
357 ((SfxFilterMatcher_Impl*)this)->pList = new SfxFilterList_Impl;
358 ((SfxFilterMatcher_Impl*)this)->Update();
360 else
362 // global matcher: use global filter array
363 ((SfxFilterMatcher_Impl*)this)->pList = pFilterArr;
367 const SfxFilter* SfxFilterMatcher::GetAnyFilter( SfxFilterFlags nMust, SfxFilterFlags nDont ) const
369 m_rImpl.InitForIterating();
370 for ( size_t i = 0, n = m_rImpl.pList->size(); i < n; ++i )
372 const SfxFilter* pFilter = m_rImpl.pList->at( i );
373 SfxFilterFlags nFlags = pFilter->GetFilterFlags();
374 if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) )
375 return pFilter;
378 return NULL;
381 //----------------------------------------------------------------
383 sal_uInt32 SfxFilterMatcher::GuessFilterIgnoringContent(
384 SfxMedium& rMedium,
385 const SfxFilter**ppFilter,
386 SfxFilterFlags nMust,
387 SfxFilterFlags nDont ) const
389 Reference< XTypeDetection > xDetection( ::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString("com.sun.star.document.TypeDetection")), UNO_QUERY );
390 ::rtl::OUString sTypeName;
393 sTypeName = xDetection->queryTypeByURL( rMedium.GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) );
395 catch( Exception& )
399 *ppFilter = NULL;
400 if ( !sTypeName.isEmpty() )
402 // make sure filter list is initialized
403 m_rImpl.InitForIterating();
404 *ppFilter = GetFilter4EA( sTypeName, nMust, nDont );
407 return *ppFilter ? ERRCODE_NONE : ERRCODE_ABORT;
410 //----------------------------------------------------------------
412 sal_uInt32 SfxFilterMatcher::GuessFilter( SfxMedium& rMedium, const SfxFilter**ppFilter, SfxFilterFlags nMust, SfxFilterFlags nDont ) const
414 return GuessFilterControlDefaultUI( rMedium, ppFilter, nMust, nDont, sal_True );
417 //----------------------------------------------------------------
419 sal_uInt32 SfxFilterMatcher::GuessFilterControlDefaultUI( SfxMedium& rMedium, const SfxFilter** ppFilter, SfxFilterFlags nMust, SfxFilterFlags nDont, sal_Bool /*bDefUI*/ ) const
421 const SfxFilter* pOldFilter = *ppFilter;
423 // no detection service -> nothing to do !
424 Reference< XTypeDetection > xDetection( ::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString("com.sun.star.document.TypeDetection")), UNO_QUERY );
425 if (!xDetection.is())
426 return ERRCODE_ABORT;
428 ::rtl::OUString sTypeName;
431 // open the stream one times only ...
432 // Otherwhise it will be tried more then once and show the same interaction more then once ...
434 ::rtl::OUString sURL( rMedium.GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) );
435 ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > xInStream = rMedium.GetInputStream();
436 rtl::OUString aFilterName;
438 // stream exists => deep detection (with preselection ... if possible)
439 if (xInStream.is())
441 ::comphelper::MediaDescriptor aDescriptor;
443 aDescriptor[::comphelper::MediaDescriptor::PROP_URL() ] <<= sURL;
444 aDescriptor[::comphelper::MediaDescriptor::PROP_INPUTSTREAM() ] <<= xInStream;
445 aDescriptor[::comphelper::MediaDescriptor::PROP_INTERACTIONHANDLER()] <<= rMedium.GetInteractionHandler();
447 if ( !m_rImpl.aName.isEmpty() )
448 aDescriptor[::comphelper::MediaDescriptor::PROP_DOCUMENTSERVICE()] <<= m_rImpl.aName;
450 if ( pOldFilter )
452 aDescriptor[::comphelper::MediaDescriptor::PROP_TYPENAME() ] <<= ::rtl::OUString( pOldFilter->GetTypeName() );
453 aDescriptor[::comphelper::MediaDescriptor::PROP_FILTERNAME()] <<= ::rtl::OUString( pOldFilter->GetFilterName() );
456 ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > lDescriptor = aDescriptor.getAsConstPropertyValueList();
457 sTypeName = xDetection->queryTypeByDescriptor(lDescriptor, sal_True); // lDescriptor is used as In/Out param ... dont use aDescriptor.getAsConstPropertyValueList() directly!
459 for (sal_Int32 i = 0; i < lDescriptor.getLength(); ++i)
461 if (lDescriptor[i].Name == "FilterName")
462 // Type detection picked a preferred filter for this format.
463 aFilterName = lDescriptor[i].Value.get<rtl::OUString>();
466 // no stream exists => try flat detection without preselection as fallback
467 else
468 sTypeName = xDetection->queryTypeByURL(sURL);
470 if (!sTypeName.isEmpty())
472 const SfxFilter* pFilter = NULL;
473 if (!aFilterName.isEmpty())
474 // Type detection returned a suitable filter for this. Use it.
475 pFilter = SfxFilter::GetFilterByName(aFilterName);
477 if (!pFilter)
479 // detect filter by given type
480 // In case of this matcher is bound to a particular document type:
481 // If there is no acceptable type for this document at all, the type detection has possibly returned something else.
482 // The DocumentService property is only a preselection, and all preselections are considered as optional!
483 // This "wrong" type will be sorted out now because we match only allowed filters to the detected type
484 ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue > lQuery(1);
485 lQuery[0].Name = ::rtl::OUString("Name");
486 lQuery[0].Value <<= sTypeName;
488 pFilter = GetFilterForProps(lQuery, nMust, nDont);
491 if (pFilter)
493 *ppFilter = pFilter;
494 return ERRCODE_NONE;
498 catch(const Exception&)
501 return ERRCODE_ABORT;
504 //----------------------------------------------------------------
505 sal_Bool SfxFilterMatcher::IsFilterInstalled_Impl( const SfxFilter* pFilter )
507 if ( pFilter->GetFilterFlags() & SFX_FILTER_MUSTINSTALL )
509 // Here could a re-installation be offered
510 String aText( SfxResId( STR_FILTER_NOT_INSTALLED ) );
511 aText.SearchAndReplaceAscii( "$(FILTER)", pFilter->GetUIName() );
512 QueryBox aQuery( NULL, WB_YES_NO | WB_DEF_YES, aText );
513 short nRet = aQuery.Execute();
514 if ( nRet == RET_YES )
516 #ifdef DBG_UTIL
517 // Start Setup
518 InfoBox( NULL, DEFINE_CONST_UNICODE("Here should the Setup now be starting!") ).Execute();
519 #endif
520 // Installation must still give feedback if it worked or not,
521 // then the Filterflag be deleted
524 return ( !(pFilter->GetFilterFlags() & SFX_FILTER_MUSTINSTALL) );
526 else if ( pFilter->GetFilterFlags() & SFX_FILTER_CONSULTSERVICE )
528 String aText( SfxResId( STR_FILTER_CONSULT_SERVICE ) );
529 aText.SearchAndReplaceAscii( "$(FILTER)", pFilter->GetUIName() );
530 InfoBox ( NULL, aText ).Execute();
531 return sal_False;
533 else
534 return sal_True;
538 sal_uInt32 SfxFilterMatcher::DetectFilter( SfxMedium& rMedium, const SfxFilter**ppFilter, sal_Bool /*bPlugIn*/, sal_Bool bAPI ) const
539 /* [Description]
541 Here the Filter selection box is pulled up. Otherwise GuessFilter
545 const SfxFilter* pOldFilter = rMedium.GetFilter();
546 if ( pOldFilter )
548 if( !IsFilterInstalled_Impl( pOldFilter ) )
549 pOldFilter = 0;
550 else
552 SFX_ITEMSET_ARG( rMedium.GetItemSet(), pSalvageItem, SfxStringItem, SID_DOC_SALVAGE, sal_False);
553 if ( ( pOldFilter->GetFilterFlags() & SFX_FILTER_PACKED ) && pSalvageItem )
554 // Salvage is always done without packing
555 pOldFilter = 0;
559 const SfxFilter* pFilter = pOldFilter;
561 sal_Bool bPreview = rMedium.IsPreview_Impl();
562 SFX_ITEMSET_ARG(rMedium.GetItemSet(), pReferer, SfxStringItem, SID_REFERER, sal_False);
563 if ( bPreview && rMedium.IsRemote() && ( !pReferer || pReferer->GetValue().CompareToAscii("private:searchfolder:",21 ) != COMPARE_EQUAL ) )
564 return ERRCODE_ABORT;
566 ErrCode nErr = GuessFilter( rMedium, &pFilter );
567 if ( nErr == ERRCODE_ABORT )
568 return nErr;
570 if ( nErr == ERRCODE_IO_PENDING )
572 *ppFilter = pFilter;
573 return nErr;
576 if ( !pFilter )
578 const SfxFilter* pInstallFilter = NULL;
580 // Now test the filter which are not installed (ErrCode is irrelevant)
581 GuessFilter( rMedium, &pInstallFilter, SFX_FILTER_IMPORT, SFX_FILTER_CONSULTSERVICE );
582 if ( pInstallFilter )
584 if ( IsFilterInstalled_Impl( pInstallFilter ) )
585 // Maybe the filter was installed was installed afterwards.
586 pFilter = pInstallFilter;
588 else
590 // Now test the filter, which first must be obtained by Star
591 // (ErrCode is irrelevant)
592 GuessFilter( rMedium, &pInstallFilter, SFX_FILTER_IMPORT, 0 );
593 if ( pInstallFilter )
594 IsFilterInstalled_Impl( pInstallFilter );
598 sal_Bool bHidden = bPreview;
599 SFX_ITEMSET_ARG( rMedium.GetItemSet(), pFlags, SfxStringItem, SID_OPTIONS, sal_False);
600 if ( !bHidden && pFlags )
602 String aFlags( pFlags->GetValue() );
603 aFlags.ToUpperAscii();
604 if( STRING_NOTFOUND != aFlags.Search( 'H' ) )
605 bHidden = sal_True;
607 *ppFilter = pFilter;
609 if ( bHidden || (bAPI && nErr == ERRCODE_SFX_CONSULTUSER) )
610 nErr = pFilter ? ERRCODE_NONE : ERRCODE_ABORT;
611 return nErr;
614 const SfxFilter* SfxFilterMatcher::GetFilterForProps( const com::sun::star::uno::Sequence < ::com::sun::star::beans::NamedValue >& aSeq, SfxFilterFlags nMust, SfxFilterFlags nDont ) const
616 ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory();
617 ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerQuery > xTypeCFG;
618 if( xServiceManager.is() == sal_True )
619 xTypeCFG = ::com::sun::star::uno::Reference < com::sun::star::container::XContainerQuery >( xServiceManager->createInstance( DEFINE_CONST_UNICODE( "com.sun.star.document.TypeDetection" ) ), ::com::sun::star::uno::UNO_QUERY );
620 if ( xTypeCFG.is() )
622 // make query for all types matching the properties
623 ::com::sun::star::uno::Reference < com::sun::star::container::XEnumeration > xEnum = xTypeCFG->createSubSetEnumerationByProperties( aSeq );
624 while ( xEnum->hasMoreElements() )
626 ::comphelper::SequenceAsHashMap aProps( xEnum->nextElement() );
627 ::rtl::OUString aValue;
629 // try to get the preferred filter (works without loading all filters!)
630 if ( (aProps[::rtl::OUString("PreferredFilter")] >>= aValue) && !aValue.isEmpty() )
632 const SfxFilter* pFilter = SfxFilter::GetFilterByName( aValue );
633 if ( !pFilter || (pFilter->GetFilterFlags() & nMust) != nMust || (pFilter->GetFilterFlags() & nDont ) )
634 // check for filter flags
635 // pFilter == 0: if preferred filter is a Writer filter, but Writer module is not installed
636 continue;
638 if ( !m_rImpl.aName.isEmpty() )
640 // if this is not the global FilterMatcher: check if filter matches the document type
641 if ( pFilter->GetServiceName() != String(m_rImpl.aName) )
643 // preferred filter belongs to another document type; now we must search the filter
644 m_rImpl.InitForIterating();
645 aProps[::rtl::OUString("Name")] >>= aValue;
646 pFilter = GetFilter4EA( aValue, nMust, nDont );
647 if ( pFilter )
648 return pFilter;
650 else
651 return pFilter;
653 else
654 return pFilter;
659 return 0;
662 const SfxFilter* SfxFilterMatcher::GetFilter4Mime( const ::rtl::OUString& rMediaType, SfxFilterFlags nMust, SfxFilterFlags nDont ) const
664 if ( m_rImpl.pList )
666 for ( size_t i = 0, n = m_rImpl.pList->size(); i < n; ++i )
668 const SfxFilter* pFilter = m_rImpl.pList->at( i );
669 SfxFilterFlags nFlags = pFilter->GetFilterFlags();
670 if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) && pFilter->GetMimeType() == rMediaType )
671 return pFilter;
674 return 0;
677 com::sun::star::uno::Sequence < com::sun::star::beans::NamedValue > aSeq(1);
678 aSeq[0].Name = ::rtl::OUString("MediaType");
679 aSeq[0].Value <<= rMediaType;
680 return GetFilterForProps( aSeq, nMust, nDont );
683 const SfxFilter* SfxFilterMatcher::GetFilter4EA( const String& rType,SfxFilterFlags nMust, SfxFilterFlags nDont ) const
685 if ( m_rImpl.pList )
687 const SfxFilter* pFirst = 0;
688 for ( size_t i = 0, n = m_rImpl.pList->size(); i < n; ++i )
690 const SfxFilter* pFilter = m_rImpl.pList->at( i );
691 SfxFilterFlags nFlags = pFilter->GetFilterFlags();
692 if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) && pFilter->GetTypeName() == rType )
694 if (nFlags & SFX_FILTER_PREFERED)
695 return pFilter;
696 if (!pFirst)
697 pFirst = pFilter;
700 if (pFirst)
701 return pFirst;
703 return 0;
706 com::sun::star::uno::Sequence < com::sun::star::beans::NamedValue > aSeq(1);
707 aSeq[0].Name = ::rtl::OUString("Name");
708 aSeq[0].Value <<= ::rtl::OUString( rType );
709 return GetFilterForProps( aSeq, nMust, nDont );
712 const SfxFilter* SfxFilterMatcher::GetFilter4Extension( const String& rExt, SfxFilterFlags nMust, SfxFilterFlags nDont ) const
714 if ( m_rImpl.pList )
716 for ( size_t i = 0, n = m_rImpl.pList->size(); i < n; ++i )
718 const SfxFilter* pFilter = m_rImpl.pList->at( i );
719 SfxFilterFlags nFlags = pFilter->GetFilterFlags();
720 if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) )
722 String sWildCard = ToUpper_Impl( pFilter->GetWildcard().getGlob() );
723 String sExt = ToUpper_Impl( rExt );
725 if (!sExt.Len())
726 continue;
728 if (sExt.GetChar(0) != (sal_Unicode)'.')
729 sExt.Insert((sal_Unicode)'.', 0);
731 WildCard aCheck(sWildCard, ';');
732 if (aCheck.Matches(sExt))
733 return pFilter;
737 return 0;
740 // Use extension without dot!
741 String sExt( rExt );
742 if ( sExt.Len() && ( sExt.GetChar(0) == (sal_Unicode)'.' ))
743 sExt.Erase(0,1);
745 com::sun::star::uno::Sequence < com::sun::star::beans::NamedValue > aSeq(1);
746 aSeq[0].Name = ::rtl::OUString("Extensions");
747 ::com::sun::star::uno::Sequence < ::rtl::OUString > aExts(1);
748 aExts[0] = sExt;
749 aSeq[0].Value <<= aExts;
750 return GetFilterForProps( aSeq, nMust, nDont );
753 const SfxFilter* SfxFilterMatcher::GetFilter4ClipBoardId( sal_uInt32 nId, SfxFilterFlags nMust, SfxFilterFlags nDont ) const
755 if (nId == 0)
756 return 0;
758 com::sun::star::uno::Sequence < com::sun::star::beans::NamedValue > aSeq(1);
759 ::rtl::OUString aName = SotExchange::GetFormatName( nId );
760 aSeq[0].Name = ::rtl::OUString("ClipboardFormat");
761 aSeq[0].Value <<= aName;
762 return GetFilterForProps( aSeq, nMust, nDont );
765 const SfxFilter* SfxFilterMatcher::GetFilter4UIName( const String& rName, SfxFilterFlags nMust, SfxFilterFlags nDont ) const
767 m_rImpl.InitForIterating();
768 const SfxFilter* pFirstFilter=0;
769 for ( size_t i = 0, n = m_rImpl.pList->size(); i < n; ++i )
771 const SfxFilter* pFilter = m_rImpl.pList->at( i );
772 SfxFilterFlags nFlags = pFilter->GetFilterFlags();
773 if ( (nFlags & nMust) == nMust &&
774 !(nFlags & nDont ) && pFilter->GetUIName() == rName )
776 if ( pFilter->GetFilterFlags() & SFX_FILTER_PREFERED )
777 return pFilter;
778 else if ( !pFirstFilter )
779 pFirstFilter = pFilter;
782 return pFirstFilter;
785 const SfxFilter* SfxFilterMatcher::GetFilter4FilterName( const String& rName, SfxFilterFlags nMust, SfxFilterFlags nDont ) const
787 String aName( rName );
788 sal_uInt16 nIndex = aName.SearchAscii(": ");
789 if ( nIndex != STRING_NOTFOUND )
791 OSL_FAIL("Old filter name used!");
792 aName = rName.Copy( nIndex + 2 );
795 if ( bFirstRead )
797 ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory();
798 ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > xFilterCFG ;
799 ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > xTypeCFG ;
800 if( xServiceManager.is() == sal_True )
802 xFilterCFG = ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >( xServiceManager->createInstance( DEFINE_CONST_UNICODE( "com.sun.star.document.FilterFactory" ) ), ::com::sun::star::uno::UNO_QUERY );
803 xTypeCFG = ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >( xServiceManager->createInstance( DEFINE_CONST_UNICODE( "com.sun.star.document.TypeDetection" ) ), ::com::sun::star::uno::UNO_QUERY );
806 if( xFilterCFG.is() && xTypeCFG.is() )
808 if ( !pFilterArr )
809 CreateFilterArr();
810 else
812 for ( size_t i = 0, n = pFilterArr->size(); i < n; ++i )
814 const SfxFilter* pFilter = pFilterArr->at( i );
815 SfxFilterFlags nFlags = pFilter->GetFilterFlags();
816 if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) && pFilter->GetFilterName().CompareIgnoreCaseToAscii( aName ) == COMPARE_EQUAL )
817 return pFilter;
821 SfxFilterContainer::ReadSingleFilter_Impl( rName, xTypeCFG, xFilterCFG, sal_False );
825 SfxFilterList_Impl* pList = m_rImpl.pList;
826 if ( !pList )
827 pList = pFilterArr;
829 for ( size_t i = 0, n = pList->size(); i < n; ++i )
831 const SfxFilter* pFilter = pList->at( i );
832 SfxFilterFlags nFlags = pFilter->GetFilterFlags();
833 if ( (nFlags & nMust) == nMust && !(nFlags & nDont ) && pFilter->GetFilterName().CompareIgnoreCaseToAscii( aName ) == COMPARE_EQUAL )
834 return pFilter;
837 return NULL;
840 IMPL_STATIC_LINK( SfxFilterMatcher, MaybeFileHdl_Impl, String*, pString )
842 const SfxFilter* pFilter = pThis->GetFilter4Extension( *pString, SFX_FILTER_IMPORT );
843 if (pFilter && !pFilter->GetWildcard().Matches( String() ) &&
844 !pFilter->GetWildcard().Matches(DEFINE_CONST_UNICODE("*.*")) &&
845 !pFilter->GetWildcard().Matches('*')
848 return sal_True;
850 return sal_False;
853 //----------------------------------------------------------------
855 SfxFilterMatcherIter::SfxFilterMatcherIter(
856 const SfxFilterMatcher& rMatcher,
857 SfxFilterFlags nOrMaskP, SfxFilterFlags nAndMaskP )
858 : nOrMask( nOrMaskP ), nAndMask( nAndMaskP ),
859 nCurrent(0), m_rMatch(rMatcher.m_rImpl)
861 if( nOrMask == 0xffff ) //Due to falty build on s
862 nOrMask = 0;
863 m_rMatch.InitForIterating();
866 //----------------------------------------------------------------
868 const SfxFilter* SfxFilterMatcherIter::Find_Impl()
870 const SfxFilter* pFilter = 0;
871 while( nCurrent < m_rMatch.pList->size() )
873 pFilter = m_rMatch.pList->at( nCurrent++ );
874 SfxFilterFlags nFlags = pFilter->GetFilterFlags();
875 if( ((nFlags & nOrMask) == nOrMask ) && !(nFlags & nAndMask ) )
876 break;
877 pFilter = 0;
880 return pFilter;
883 const SfxFilter* SfxFilterMatcherIter::First()
885 nCurrent = 0;
886 return Find_Impl();
889 //----------------------------------------------------------------
891 const SfxFilter* SfxFilterMatcherIter::Next()
893 return Find_Impl();
896 /*---------------------------------------------------------------
897 helper to build own formated string from given stringlist by
898 using given seperator
899 ---------------------------------------------------------------*/
900 ::rtl::OUString implc_convertStringlistToString( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& lList ,
901 const sal_Unicode& cSeperator,
902 const ::rtl::OUString& sPrefix )
904 ::rtl::OUStringBuffer sString ( 1000 ) ;
905 sal_Int32 nCount = lList.getLength();
906 sal_Int32 nItem = 0 ;
907 for( nItem=0; nItem<nCount; ++nItem )
909 if( !sPrefix.isEmpty() )
911 sString.append( sPrefix );
913 sString.append( lList[nItem] );
914 if( nItem+1<nCount )
916 sString.append( cSeperator );
919 return sString.makeStringAndClear();
923 void SfxFilterContainer::ReadSingleFilter_Impl(
924 const ::rtl::OUString& rName,
925 const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& xTypeCFG,
926 const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& xFilterCFG,
927 sal_Bool bUpdate
930 ::rtl::OUString sFilterName( rName );
931 SfxFilterList_Impl& rList = *pFilterArr;
932 ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > lFilterProperties ;
933 ::com::sun::star::uno::Any aResult;
936 aResult = xFilterCFG->getByName( sFilterName );
938 catch( ::com::sun::star::container::NoSuchElementException& )
940 aResult = ::com::sun::star::uno::Any();
943 if( aResult >>= lFilterProperties )
945 // collect informations to add filter to container
946 // (attention: some informations aren't available on filter directly ... you must search for corresponding type too!)
947 sal_Int32 nFlags = 0 ;
948 sal_Int32 nClipboardId = 0 ;
949 sal_Int32 nDocumentIconId = 0 ;
950 sal_Int32 nFormatVersion = 0 ;
951 ::rtl::OUString sMimeType ;
952 ::rtl::OUString sType ;
953 ::rtl::OUString sUIName ;
954 ::rtl::OUString sHumanName ;
955 ::rtl::OUString sDefaultTemplate ;
956 ::rtl::OUString sUserData ;
957 ::rtl::OUString sExtension ;
958 ::rtl::OUString sPattern ;
959 ::rtl::OUString sServiceName ;
961 // first get directly available properties
962 sal_Int32 nFilterPropertyCount = lFilterProperties.getLength();
963 sal_Int32 nFilterProperty = 0 ;
964 for( nFilterProperty=0; nFilterProperty<nFilterPropertyCount; ++nFilterProperty )
966 if ( lFilterProperties[nFilterProperty].Name == "FileFormatVersion" )
968 lFilterProperties[nFilterProperty].Value >>= nFormatVersion;
970 else if ( lFilterProperties[nFilterProperty].Name == "TemplateName" )
972 lFilterProperties[nFilterProperty].Value >>= sDefaultTemplate;
974 else if ( lFilterProperties[nFilterProperty].Name == "Flags" )
976 lFilterProperties[nFilterProperty].Value >>= nFlags;
978 else if ( lFilterProperties[nFilterProperty].Name == "UIName" )
980 lFilterProperties[nFilterProperty].Value >>= sUIName;
982 else if ( lFilterProperties[nFilterProperty].Name == "UserData" )
984 ::com::sun::star::uno::Sequence< ::rtl::OUString > lUserData;
985 lFilterProperties[nFilterProperty].Value >>= lUserData;
986 sUserData = implc_convertStringlistToString( lUserData, ',', ::rtl::OUString() );
988 else if ( lFilterProperties[nFilterProperty].Name == "DocumentService" )
990 lFilterProperties[nFilterProperty].Value >>= sServiceName;
992 else if ( lFilterProperties[nFilterProperty].Name == "Type" )
994 lFilterProperties[nFilterProperty].Value >>= sType;
995 // Try to get filter .. but look for any exceptions!
996 // May be filter was deleted by another thread ...
999 aResult = xTypeCFG->getByName( sType );
1001 catch (const ::com::sun::star::container::NoSuchElementException&)
1003 aResult = ::com::sun::star::uno::Any();
1006 ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > lTypeProperties;
1007 if( aResult >>= lTypeProperties )
1009 // get indirect available properties then (types)
1010 sal_Int32 nTypePropertyCount = lTypeProperties.getLength();
1011 sal_Int32 nTypeProperty = 0 ;
1012 for( nTypeProperty=0; nTypeProperty<nTypePropertyCount; ++nTypeProperty )
1014 if ( lTypeProperties[nTypeProperty].Name == "ClipboardFormat" )
1016 lTypeProperties[nTypeProperty].Value >>= sHumanName;
1018 else if ( lTypeProperties[nTypeProperty].Name == "DocumentIconID" )
1020 lTypeProperties[nTypeProperty].Value >>= nDocumentIconId;
1022 else if ( lTypeProperties[nTypeProperty].Name == "MediaType" )
1024 lTypeProperties[nTypeProperty].Value >>= sMimeType;
1026 else if ( lTypeProperties[nTypeProperty].Name == "Extensions" )
1028 ::com::sun::star::uno::Sequence< ::rtl::OUString > lExtensions;
1029 lTypeProperties[nTypeProperty].Value >>= lExtensions;
1030 sExtension = implc_convertStringlistToString( lExtensions, ';', DEFINE_CONST_UNICODE("*.") );
1032 else if ( lTypeProperties[nTypeProperty].Name == "URLPattern" )
1034 ::com::sun::star::uno::Sequence< ::rtl::OUString > lPattern;
1035 lTypeProperties[nTypeProperty].Value >>= lPattern;
1036 sPattern = implc_convertStringlistToString( lPattern, ';', ::rtl::OUString() );
1043 if ( sServiceName.isEmpty() )
1044 return;
1046 // old formats are found ... using HumanPresentableName!
1047 if( !sHumanName.isEmpty() )
1049 nClipboardId = SotExchange::RegisterFormatName( sHumanName );
1051 // For external filters ignore clipboard IDs
1052 if((nFlags & SFX_FILTER_STARONEFILTER) == SFX_FILTER_STARONEFILTER)
1054 nClipboardId = 0;
1057 // register SfxFilter
1058 // first erase module name from old filter names!
1059 // e.g: "scalc: DIF" => "DIF"
1060 sal_Int32 nStartRealName = sFilterName.indexOf( DEFINE_CONST_UNICODE(": "), 0 );
1061 if( nStartRealName != -1 )
1063 OSL_FAIL("Old format, not supported!");
1064 sFilterName = sFilterName.copy( nStartRealName+2 );
1067 SfxFilter* pFilter = bUpdate ? (SfxFilter*) SfxFilter::GetFilterByName( sFilterName ) : 0;
1068 sal_Bool bNew = sal_False;
1069 if (!pFilter)
1071 bNew = sal_True;
1072 pFilter = new SfxFilter( sFilterName ,
1073 sExtension ,
1074 nFlags ,
1075 nClipboardId ,
1076 sType ,
1077 (sal_uInt16)nDocumentIconId ,
1078 sMimeType ,
1079 sUserData ,
1080 sServiceName );
1082 else
1084 pFilter->aFilterName = sFilterName;
1085 pFilter->aWildCard = WildCard(sExtension, ';');
1086 pFilter->nFormatType = nFlags;
1087 pFilter->lFormat = nClipboardId;
1088 pFilter->aTypeName = sType;
1089 pFilter->nDocIcon = (sal_uInt16)nDocumentIconId;
1090 pFilter->aMimeType = sMimeType;
1091 pFilter->aUserData = sUserData;
1092 pFilter->aServiceName = sServiceName;
1095 // Don't forget to set right UIName!
1096 // Otherwise internal name is used as fallback ...
1097 pFilter->SetUIName( sUIName );
1098 pFilter->SetDefaultTemplate( sDefaultTemplate );
1099 if( nFormatVersion )
1101 pFilter->SetVersion( nFormatVersion );
1103 pFilter->SetURLPattern(sPattern);
1105 if (bNew)
1106 rList.push_back( pFilter );
1110 void SfxFilterContainer::ReadFilters_Impl( sal_Bool bUpdate )
1112 RTL_LOGFILE_CONTEXT( aMeasure, "sfx2 (as96863) ::SfxFilterContainer::ReadFilters" );
1113 if ( !pFilterArr )
1114 CreateFilterArr();
1116 bFirstRead = sal_False;
1117 SfxFilterList_Impl& rList = *pFilterArr;
1121 // get the FilterFactory service to access the registered filters ... and types!
1122 ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory();
1123 ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > xFilterCFG ;
1124 ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > xTypeCFG ;
1125 if( xServiceManager.is() == sal_True )
1127 xFilterCFG = ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >( xServiceManager->createInstance( DEFINE_CONST_UNICODE( "com.sun.star.document.FilterFactory" ) ), ::com::sun::star::uno::UNO_QUERY );
1128 xTypeCFG = ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >( xServiceManager->createInstance( DEFINE_CONST_UNICODE( "com.sun.star.document.TypeDetection" ) ), ::com::sun::star::uno::UNO_QUERY );
1132 ( xFilterCFG.is() == sal_True ) &&
1133 ( xTypeCFG.is() == sal_True )
1136 // select right query to get right set of filters for search modul
1137 ::com::sun::star::uno::Sequence< ::rtl::OUString > lFilterNames = xFilterCFG->getElementNames();
1138 if ( lFilterNames.getLength() )
1140 // If list of filters already exist ...
1141 // ReadExternalFilters must work in update mode.
1142 // Best way seams to mark all filters NOT_INSTALLED
1143 // and change it back for all valid filters afterwards.
1144 if( !rList.empty() )
1146 bUpdate = sal_True;
1147 SfxFilter* pFilter;
1148 for ( size_t i = 0, n = rList.size(); i < n; ++i )
1150 pFilter = NULL;
1151 pFilter = rList[ i ];
1152 pFilter->nFormatType |= SFX_FILTER_NOTINSTALLED;
1156 // get all properties of filters ... put it into the filter container
1157 sal_Int32 nFilterCount = lFilterNames.getLength();
1158 sal_Int32 nFilter=0;
1159 for( nFilter=0; nFilter<nFilterCount; ++nFilter )
1161 // Try to get filter .. but look for any exceptions!
1162 // May be filter was deleted by another thread ...
1163 ::rtl::OUString sFilterName = lFilterNames[nFilter];
1164 ReadSingleFilter_Impl( sFilterName, xTypeCFG, xFilterCFG, bUpdate );
1169 catch(const ::com::sun::star::uno::Exception&)
1171 DBG_ASSERT( sal_False, "SfxFilterContainer::ReadFilter()\nException detected. Possible not all filters could be cached.\n" );
1174 if ( bUpdate )
1176 // global filter arry was modified, factory specific ones might need an
1177 // update too
1178 std::for_each(aImplArr.begin(), aImplArr.end(),
1179 std::mem_fun_ref(&SfxFilterMatcher_Impl::Update));
1183 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */