1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: FilterHelper.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
33 #include <vos/mutex.hxx>
34 #include <vcl/svapp.hxx>
36 // #ifndef _OSL_DIAGNOSE_H_
37 // #include <osl/diagnose.h>
39 #include "CFStringUtilities.hxx"
40 #include "NSString_OOoAdditions.hxx"
42 #include "FilterHelper.hxx"
45 #define CLASS_NAME "FilterEntry"
47 #pragma mark FilterEntry
48 //---------------------------------------------------------------------
49 FilterEntry::FilterEntry( const rtl::OUString
& _rTitle
, const UnoFilterList
& _rSubFilters
)
51 ,m_aSubFilters( _rSubFilters
)
53 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
, "title", _rTitle
);
54 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
57 //---------------------------------------------------------------------
58 sal_Bool
FilterEntry::hasSubFilters() const
60 // OSL_TRACE(">>> FilterEntry::%s", __func__);
61 sal_Bool bReturn
= ( 0 < m_aSubFilters
.getLength() );
62 // OSL_TRACE("<<< FilterEntry::%s retVal: %d", __func__, bReturn);
66 //---------------------------------------------------------------------
67 sal_Int32
FilterEntry::getSubFilters( UnoFilterList
& _rSubFilterList
)
69 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
);
71 _rSubFilterList
= m_aSubFilters
;
72 sal_Int32 nReturn
= m_aSubFilters
.getLength();
74 DBG_PRINT_EXIT(CLASS_NAME
, __func__
, nReturn
);
81 isFilterString( const rtl::OUString
& rFilterString
, const char *pMatch
)
85 bool bIsFilter
= true;
87 rtl::OUString
aMatch(rtl::OUString::createFromAscii(pMatch
));
91 aToken
= rFilterString
.getToken( 0, ';', nIndex
);
92 if( !aToken
.match( aMatch
) )
103 //=====================================================================
106 shrinkFilterName( const rtl::OUString aFilterName
, bool bAllowNoStar
= false )
108 // DBG_PRINT_ENTRY(CLASS_NAME, "shrinkFilterName", "filterName", aFilterName);
111 int nBracketLen
= -1;
112 int nBracketEnd
= -1;
113 rtl::OUString rFilterName
= aFilterName
;
114 const sal_Unicode
*pStr
= rFilterName
;
115 rtl::OUString aRealName
= rFilterName
;
117 for( i
= aRealName
.getLength() - 1; i
> 0; i
-- )
121 else if( pStr
[i
] == '(' )
123 nBracketLen
= nBracketEnd
- i
;
124 if( nBracketEnd
<= 0 )
126 if( isFilterString( rFilterName
.copy( i
+ 1, nBracketLen
- 1 ), "*." ) )
127 aRealName
= aRealName
.replaceAt( i
, nBracketLen
+ 1, rtl::OUString() );
128 else if (bAllowNoStar
)
130 if( isFilterString( rFilterName
.copy( i
+ 1, nBracketLen
- 1 ), ".") )
131 aRealName
= aRealName
.replaceAt( i
, nBracketLen
+ 1, rtl::OUString() );
139 //------------------------------------------------------------------------------------
141 //................................................................................
142 struct FilterTitleMatch
: public ::std::unary_function
< FilterEntry
, bool >
145 const rtl::OUString rTitle
;
148 FilterTitleMatch( const rtl::OUString _rTitle
) : rTitle( _rTitle
) { }
150 //............................................................................
151 bool operator () ( const FilterEntry
& _rEntry
)
154 if( !_rEntry
.hasSubFilters() ) {
155 //first try the complete filter name
156 rtl::OUString title
= _rEntry
.getTitle();
157 bMatch
= ( title
.equals(rTitle
) );
159 //we didn't find a match using the full name, let's give it another
160 //try using the shrunk version
161 rtl::OUString aShrunkName
= shrinkFilterName( _rEntry
.getTitle() ).trim();
162 bMatch
= ( aShrunkName
.equals(rTitle
) );
166 // a filter group -> search the sub filters
168 _rEntry
.endSubFilters() != ::std::find_if(
169 _rEntry
.beginSubFilters(),
170 _rEntry
.endSubFilters(),
174 return bMatch
? true : false;
177 bool operator () ( const UnoFilterEntry
& _rEntry
)
179 rtl::OUString aShrunkName
= shrinkFilterName( _rEntry
.First
);
180 bool retVal
= aShrunkName
.equals(rTitle
);
187 #define CLASS_NAME "FilterHelper"
189 FilterHelper::FilterHelper()
190 : m_pFilterList(NULL
)
191 , m_pFilterNames(NULL
)
193 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
);
194 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
197 FilterHelper::~FilterHelper()
199 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
);
201 NSAutoreleasePool
*pool
= [NSAutoreleasePool
new];
203 if (NULL
!= m_pFilterList
) {
204 delete m_pFilterList
;
207 if (NULL
!= m_pFilterNames
) {
208 //we called retain when we added the strings to the list, so we should release them now
209 for (NSStringList::iterator iter
= m_pFilterNames
->begin(); iter
!= m_pFilterNames
->end(); iter
++) {
212 delete m_pFilterNames
;
217 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
220 //------------------------------------------------------------------------------------
221 sal_Bool
FilterHelper::FilterNameExists( const rtl::OUString rTitle
)
223 sal_Bool bRet
= sal_False
;
227 m_pFilterList
->end() != ::std::find_if(
228 m_pFilterList
->begin(),
229 m_pFilterList
->end(),
230 FilterTitleMatch( rTitle
)
236 //------------------------------------------------------------------------------------
237 sal_Bool
FilterHelper::FilterNameExists( const UnoFilterList
& _rGroupedFilters
)
239 sal_Bool bRet
= sal_False
;
243 const UnoFilterEntry
* pStart
= _rGroupedFilters
.getConstArray();
244 const UnoFilterEntry
* pEnd
= pStart
+ _rGroupedFilters
.getLength();
245 for( ; pStart
!= pEnd
; ++pStart
)
246 if( m_pFilterList
->end() != ::std::find_if(
247 m_pFilterList
->begin(),
248 m_pFilterList
->end(),
249 FilterTitleMatch( pStart
->First
) ) )
252 bRet
= (pStart
!= pEnd
);
258 //------------------------------------------------------------------------------------
259 void FilterHelper::ensureFilterList( const ::rtl::OUString
& _rInitialCurrentFilter
)
261 //OSL_TRACE(">>> FilterHelper::%s", __func__);
262 if( NULL
== m_pFilterList
)
264 m_pFilterList
= new FilterList
;
266 // set the first filter to the current filter
267 m_aCurrentFilter
= _rInitialCurrentFilter
;
268 OSL_TRACE("ensureFilterList filter:%s", OUStringToOString(m_aCurrentFilter
, RTL_TEXTENCODING_UTF8
).getStr());
270 //OSL_TRACE("<<< FilterHelper::%s", __func__);
273 void FilterHelper::SetCurFilter( const rtl::OUString
& rFilter
)
275 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
, "filter", rFilter
);
277 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
279 if(m_aCurrentFilter
.equals(rFilter
) == false)
281 m_aCurrentFilter
= rFilter
;
284 //only for output purposes
285 #if OSL_DEBUG_LEVEL > 1
286 FilterList::iterator aFilter
= ::std::find_if(m_pFilterList
->begin(), m_pFilterList
->end(), FilterTitleMatch(m_aCurrentFilter
));
287 if (aFilter
!= m_pFilterList
->end()) {
288 OUStringList suffixes
= aFilter
->getFilterSuffixList();
289 if (!suffixes
.empty()) {
290 OSL_TRACE("Current active suffixes: ");
291 OUStringList::iterator suffIter
= suffixes
.begin();
292 while(suffIter
!= suffixes
.end()) {
293 OSL_TRACE("%s", OUStringToOString((*suffIter
), RTL_TEXTENCODING_UTF8
).getStr());
298 OSL_TRACE("No filter entry was found for that name!");
302 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
305 void FilterHelper::SetFilters()
307 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
);
309 // set the default filter
310 if( m_aCurrentFilter
.getLength() > 0 )
312 OSL_TRACE( "Setting current filter to %s", OUStringToOString(m_aCurrentFilter
, RTL_TEXTENCODING_UTF8
).getStr());
314 SetCurFilter( m_aCurrentFilter
);
317 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
320 void FilterHelper::appendFilter(const ::rtl::OUString
& aTitle
, const ::rtl::OUString
& aFilterString
)
321 throw( ::com::sun::star::lang::IllegalArgumentException
, ::com::sun::star::uno::RuntimeException
) {
322 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
, "title", aTitle
, "filter", aFilterString
);
324 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
326 if( FilterNameExists( aTitle
) ) {
327 throw com::sun::star::lang::IllegalArgumentException();
330 // ensure that we have a filter list
331 ensureFilterList( aTitle
);
334 OUStringList suffixList
;
335 fillSuffixList(suffixList
, aFilterString
);
336 m_pFilterList
->push_back(FilterEntry( aTitle
, suffixList
) );
338 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
341 void FilterHelper::setCurrentFilter( const ::rtl::OUString
& aTitle
)
342 throw( ::com::sun::star::lang::IllegalArgumentException
, ::com::sun::star::uno::RuntimeException
) {
343 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
, "aTitle", OUStringToOString(aTitle
, RTL_TEXTENCODING_UTF8
).getStr());
345 SetCurFilter(aTitle
);
347 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
350 ::rtl::OUString SAL_CALL
FilterHelper::getCurrentFilter( )
351 throw( ::com::sun::star::uno::RuntimeException
) {
352 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
);
354 ::rtl::OUString sReturn
= (m_aCurrentFilter
);
356 DBG_PRINT_EXIT(CLASS_NAME
, __func__
, OUStringToOString(sReturn
, RTL_TEXTENCODING_UTF8
).getStr());
361 void SAL_CALL
FilterHelper::appendFilterGroup( const ::rtl::OUString
& sGroupTitle
, const ::com::sun::star::uno::Sequence
< ::com::sun::star::beans::StringPair
>& aFilters
)
362 throw (::com::sun::star::lang::IllegalArgumentException
, ::com::sun::star::uno::RuntimeException
) {
364 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
, "title", OUStringToOString(sGroupTitle
, RTL_TEXTENCODING_UTF8
).getStr());
366 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
368 //add a separator if this is not the first group to be added
369 sal_Bool bPrependSeparator
= m_pFilterList
!= NULL
;
371 // ensure that we have a filter list
372 ::rtl::OUString sInitialCurrentFilter
;
373 if( aFilters
.getLength() > 0)
374 sInitialCurrentFilter
= aFilters
[0].First
;
375 ensureFilterList( sInitialCurrentFilter
);
378 if (bPrependSeparator
) {
379 rtl::OUString dash
= rtl::OUString::createFromAscii("-");
380 OUStringList emptyList
;
381 m_pFilterList
->push_back(FilterEntry(dash
, emptyList
));
384 const com::sun::star::beans::StringPair
* pSubFilters
= aFilters
.getConstArray();
385 const com::sun::star::beans::StringPair
* pSubFiltersEnd
= pSubFilters
+ aFilters
.getLength();
386 for( ; pSubFilters
!= pSubFiltersEnd
; ++pSubFilters
) {
387 appendFilter(pSubFilters
->First
, pSubFilters
->Second
);
390 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
393 sal_Bool
FilterHelper::filenameMatchesFilter(NSString
* sFilename
)
395 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
);
397 // OSL_TRACE("filter event handler called");
399 if (m_aCurrentFilter
== NULL
) {
400 OSL_TRACE("filter name is null");
404 NSFileManager
*manager
= [NSFileManager defaultManager
];
406 if ([manager fileExistsAtPath
:sFilename isDirectory
:&bDir
] && bDir
== YES
) {
407 // OSL_TRACE(" folder");
411 NSFileWrapper
*wrapper
= [[NSFileWrapper alloc
] initWithPath
:sFilename
];
412 MacOSBOOL bIsLink
= [wrapper isSymbolicLink
];
415 // OSL_TRACE(" symboliclink");
419 // OSL_TRACE(" file");
421 FilterList::iterator filter
= ::std::find_if(m_pFilterList
->begin(), m_pFilterList
->end(), FilterTitleMatch(m_aCurrentFilter
));
422 if (filter
== m_pFilterList
->end()) {
423 OSL_TRACE("filter not found in list");
427 OUStringList suffixList
= filter
->getFilterSuffixList();
430 // OSL_TRACE(" starting to work");
431 rtl::OUString aName
= [sFilename OUString
];
432 rtl::OUString allMatcher
= rtl::OUString::createFromAscii(".*");
433 for(OUStringList::iterator iter
= suffixList
.begin(); iter
!= suffixList
.end(); iter
++) {
434 if (aName
.matchIgnoreAsciiCase(*iter
, aName
.getLength() - (*iter
).getLength()) || ((*iter
).equals(allMatcher
))) {
440 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
445 FilterList
* FilterHelper::getFilterList() {
446 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
);
447 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
449 return m_pFilterList
;
452 NSStringList
* FilterHelper::getFilterNames() {
453 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
);
455 if (NULL
== m_pFilterList
)
457 if (NULL
== m_pFilterNames
) {
458 //build filter names list
459 m_pFilterNames
= new NSStringList
;
460 for (FilterList::iterator iter
= m_pFilterList
->begin(); iter
!= m_pFilterList
->end(); iter
++) {
461 m_pFilterNames
->push_back([[NSString stringWithOUString
:iter
->getTitle()] retain
]);
465 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
467 return m_pFilterNames
;
470 void FilterHelper::SetFilterAtIndex(unsigned index
) {
471 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
, "index", index
);
473 if (m_pFilterList
->size() <= index
) {
476 FilterEntry entry
= m_pFilterList
->at(index
);
477 SetCurFilter(entry
.getTitle());
479 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
482 void FilterHelper::fillSuffixList(OUStringList
& aSuffixList
, const ::rtl::OUString
& suffixString
) {
483 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
, "aSuffixList", suffixString
);
485 sal_Int32 nIndex
= 0;
487 rtl::OUString aToken
= suffixString
.getToken( 0, ';', nIndex
);
488 aSuffixList
.push_back(aToken
.copy(1));
489 } while ( nIndex
>= 0 );
491 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);
494 int FilterHelper::getCurrentFilterIndex() {
495 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
);
497 int result
= 0;//default to first filter
498 if (m_aCurrentFilter
.getLength() > 0) {
500 for (FilterList::iterator iter
= m_pFilterList
->begin(); iter
!= m_pFilterList
->end(); iter
++, i
++) {
501 rtl::OUString aTitle
= iter
->getTitle();
502 if (m_aCurrentFilter
.equals(aTitle
)) {
506 aTitle
= shrinkFilterName(aTitle
).trim();
507 if (m_aCurrentFilter
.equals(aTitle
)) {
515 DBG_PRINT_EXIT(CLASS_NAME
, __func__
, result
);
520 OUStringList
FilterHelper::getCurrentFilterSuffixList() {
521 DBG_PRINT_ENTRY(CLASS_NAME
, __func__
);
524 if (m_aCurrentFilter
.getLength() > 0) {
525 for (FilterList::iterator iter
= m_pFilterList
->begin(); iter
!= m_pFilterList
->end(); iter
++) {
526 rtl::OUString aTitle
= iter
->getTitle();
527 if (m_aCurrentFilter
.equals(aTitle
)) {
528 retVal
= iter
->getFilterSuffixList();
531 aTitle
= shrinkFilterName(aTitle
).trim();
532 if (m_aCurrentFilter
.equals(aTitle
)) {
533 retVal
= iter
->getFilterSuffixList();
540 DBG_PRINT_EXIT(CLASS_NAME
, __func__
);