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 ************************************************************************/
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>
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
150 SfxFilterContainer_Impl( const String
& 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()
188 //----------------------------------------------------------------
190 const String
SfxFilterContainer::GetName() const
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
)
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
);
222 (pFilter
->GetServiceName().CompareIgnoreCaseToAscii( sServiceName
) != COMPARE_EQUAL
)
228 // If at least no default filter could be located - use any filter of this
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
;
250 //----------------------------------------------------------------
252 // Impl-Data is shared between all FilterMatchers of the same factory
253 class SfxFilterMatcher_Impl
256 ::rtl::OUString aName
;
257 SfxFilterList_Impl
* pList
; // is created on demand
259 void InitForIterating() const;
261 SfxFilterMatcher_Impl(const ::rtl::OUString
&rName
)
270 typedef boost::ptr_vector
<SfxFilterMatcher_Impl
> SfxFilterMatcherArr_Impl
;
271 static SfxFilterMatcherArr_Impl aImplArr
;
272 static int nSfxFilterMatcherCount
;
275 public std::unary_function
<SfxFilterMatcher_Impl
, bool>
278 const rtl::OUString
& mrName
;
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
)
291 if (!rName
.isEmpty())
292 aName
= SfxObjectShell::GetServiceNameFromFactory(rName
);
294 // find the impl-Data of any comparable FilterMatcher that was created
296 SfxFilterMatcherArr_Impl::iterator aEnd
= aImplArr
.end();
297 SfxFilterMatcherArr_Impl::iterator aIter
=
298 std::find_if(aImplArr
.begin(), aEnd
, hasName(rName
));
302 // first Matcher created for this factory
303 SfxFilterMatcher_Impl
*pImpl
= new SfxFilterMatcher_Impl(aName
);
304 aImplArr
.push_back(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
320 ++nSfxFilterMatcherCount
;
323 SfxFilterMatcher::~SfxFilterMatcher()
325 --nSfxFilterMatcherCount
;
326 if (nSfxFilterMatcherCount
== 0)
330 void SfxFilterMatcher_Impl::Update()
334 // this List was already used
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
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();
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
) )
381 //----------------------------------------------------------------
383 sal_uInt32
SfxFilterMatcher::GuessFilterIgnoringContent(
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
) );
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)
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
;
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
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
);
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
);
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
)
518 InfoBox( NULL
, DEFINE_CONST_UNICODE("Here should the Setup now be starting!") ).Execute();
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();
538 sal_uInt32
SfxFilterMatcher::DetectFilter( SfxMedium
& rMedium
, const SfxFilter
**ppFilter
, sal_Bool
/*bPlugIn*/, sal_Bool bAPI
) const
541 Here the Filter selection box is pulled up. Otherwise GuessFilter
545 const SfxFilter
* pOldFilter
= rMedium
.GetFilter();
548 if( !IsFilterInstalled_Impl( pOldFilter
) )
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
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
)
570 if ( nErr
== ERRCODE_IO_PENDING
)
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
;
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' ) )
609 if ( bHidden
|| (bAPI
&& nErr
== ERRCODE_SFX_CONSULTUSER
) )
610 nErr
= pFilter
? ERRCODE_NONE
: ERRCODE_ABORT
;
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
);
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
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
);
662 const SfxFilter
* SfxFilterMatcher::GetFilter4Mime( const ::rtl::OUString
& rMediaType
, SfxFilterFlags nMust
, SfxFilterFlags nDont
) const
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
)
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
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
)
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
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
);
728 if (sExt
.GetChar(0) != (sal_Unicode
)'.')
729 sExt
.Insert((sal_Unicode
)'.', 0);
731 WildCard
aCheck(sWildCard
, ';');
732 if (aCheck
.Matches(sExt
))
740 // Use extension without dot!
742 if ( sExt
.Len() && ( sExt
.GetChar(0) == (sal_Unicode
)'.' ))
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);
749 aSeq
[0].Value
<<= aExts
;
750 return GetFilterForProps( aSeq
, nMust
, nDont
);
753 const SfxFilter
* SfxFilterMatcher::GetFilter4ClipBoardId( sal_uInt32 nId
, SfxFilterFlags nMust
, SfxFilterFlags nDont
) const
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
)
778 else if ( !pFirstFilter
)
779 pFirstFilter
= pFilter
;
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 );
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() )
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
)
821 SfxFilterContainer::ReadSingleFilter_Impl( rName
, xTypeCFG
, xFilterCFG
, sal_False
);
825 SfxFilterList_Impl
* pList
= m_rImpl
.pList
;
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
)
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('*')
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
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
) )
883 const SfxFilter
* SfxFilterMatcherIter::First()
889 //----------------------------------------------------------------
891 const SfxFilter
* SfxFilterMatcherIter::Next()
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
] );
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
,
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() )
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
)
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
;
1072 pFilter
= new SfxFilter( sFilterName
,
1077 (sal_uInt16
)nDocumentIconId
,
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
);
1106 rList
.push_back( pFilter
);
1110 void SfxFilterContainer::ReadFilters_Impl( sal_Bool bUpdate
)
1112 RTL_LOGFILE_CONTEXT( aMeasure
, "sfx2 (as96863) ::SfxFilterContainer::ReadFilters" );
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() )
1148 for ( size_t i
= 0, n
= rList
.size(); i
< n
; ++i
)
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" );
1176 // global filter arry was modified, factory specific ones might need an
1178 std::for_each(aImplArr
.begin(), aImplArr
.end(),
1179 std::mem_fun_ref(&SfxFilterMatcher_Impl::Update
));
1183 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */