update dev300-m58
[ooovba.git] / fpicker / source / aqua / FilterHelper.cxx
blob75996f2d3288078650b41625431a851b6467b848
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: FilterHelper.cxx,v $
10 * $Revision: 1.5 $
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 ************************************************************************/
31 #include <functional>
32 #include <algorithm>
33 #include <vos/mutex.hxx>
34 #include <vcl/svapp.hxx>
36 // #ifndef _OSL_DIAGNOSE_H_
37 // #include <osl/diagnose.h>
38 // #endif
39 #include "CFStringUtilities.hxx"
40 #include "NSString_OOoAdditions.hxx"
42 #include "FilterHelper.hxx"
44 #pragma mark DEFINES
45 #define CLASS_NAME "FilterEntry"
47 #pragma mark FilterEntry
48 //---------------------------------------------------------------------
49 FilterEntry::FilterEntry( const rtl::OUString& _rTitle, const UnoFilterList& _rSubFilters )
50 :m_sTitle( _rTitle )
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);
63 return 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);
76 return nReturn;
79 #pragma mark statics
80 static bool
81 isFilterString( const rtl::OUString& rFilterString, const char *pMatch )
83 sal_Int32 nIndex = 0;
84 rtl::OUString aToken;
85 bool bIsFilter = true;
87 rtl::OUString aMatch(rtl::OUString::createFromAscii(pMatch));
91 aToken = rFilterString.getToken( 0, ';', nIndex );
92 if( !aToken.match( aMatch ) )
94 bIsFilter = false;
95 break;
98 while( nIndex >= 0 );
100 return bIsFilter;
103 //=====================================================================
105 static rtl::OUString
106 shrinkFilterName( const rtl::OUString aFilterName, bool bAllowNoStar = false )
108 // DBG_PRINT_ENTRY(CLASS_NAME, "shrinkFilterName", "filterName", aFilterName);
110 int i;
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-- )
119 if( pStr[i] == ')' )
120 nBracketEnd = i;
121 else if( pStr[i] == '(' )
123 nBracketLen = nBracketEnd - i;
124 if( nBracketEnd <= 0 )
125 continue;
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() );
136 return aRealName;
139 //------------------------------------------------------------------------------------
140 namespace {
141 //................................................................................
142 struct FilterTitleMatch : public ::std::unary_function< FilterEntry, bool >
144 protected:
145 const rtl::OUString rTitle;
147 public:
148 FilterTitleMatch( const rtl::OUString _rTitle ) : rTitle( _rTitle ) { }
150 //............................................................................
151 bool operator () ( const FilterEntry& _rEntry )
153 sal_Bool bMatch;
154 if( !_rEntry.hasSubFilters() ) {
155 //first try the complete filter name
156 rtl::OUString title = _rEntry.getTitle();
157 bMatch = ( title.equals(rTitle) );
158 if (!bMatch) {
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) );
165 else
166 // a filter group -> search the sub filters
167 bMatch =
168 _rEntry.endSubFilters() != ::std::find_if(
169 _rEntry.beginSubFilters(),
170 _rEntry.endSubFilters(),
171 *this
174 return bMatch ? true : false;
177 bool operator () ( const UnoFilterEntry& _rEntry )
179 rtl::OUString aShrunkName = shrinkFilterName( _rEntry.First );
180 bool retVal = aShrunkName.equals(rTitle);
181 return retVal;
186 #undef CLASS_NAME
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++) {
210 [*iter release];
212 delete m_pFilterNames;
215 [pool release];
217 DBG_PRINT_EXIT(CLASS_NAME, __func__);
220 //------------------------------------------------------------------------------------
221 sal_Bool FilterHelper::FilterNameExists( const rtl::OUString rTitle )
223 sal_Bool bRet = sal_False;
225 if( m_pFilterList )
226 bRet =
227 m_pFilterList->end() != ::std::find_if(
228 m_pFilterList->begin(),
229 m_pFilterList->end(),
230 FilterTitleMatch( rTitle )
233 return bRet;
236 //------------------------------------------------------------------------------------
237 sal_Bool FilterHelper::FilterNameExists( const UnoFilterList& _rGroupedFilters )
239 sal_Bool bRet = sal_False;
241 if( m_pFilterList )
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 ) ) )
250 break;
252 bRet = (pStart != pEnd);
255 return bRet;
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());
294 suffIter++;
297 } else {
298 OSL_TRACE("No filter entry was found for that name!");
300 #endif
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 );
333 // append the filter
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());
358 return sReturn;
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 );
377 // append the filter
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");
401 return sal_True;
404 NSFileManager *manager = [NSFileManager defaultManager];
405 MacOSBOOL bDir = NO;
406 if ([manager fileExistsAtPath:sFilename isDirectory:&bDir] && bDir == YES) {
407 // OSL_TRACE(" folder");
408 return sal_True;
411 NSFileWrapper *wrapper = [[NSFileWrapper alloc] initWithPath:sFilename];
412 MacOSBOOL bIsLink = [wrapper isSymbolicLink];
413 [wrapper release];
414 if (bIsLink) {
415 // OSL_TRACE(" symboliclink");
416 return sal_True;
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");
424 return sal_True;
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))) {
435 return sal_True;
440 DBG_PRINT_EXIT(CLASS_NAME, __func__);
442 return sal_False;
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)
456 return NULL;
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) {
474 index = 0;
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;
486 do {
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) {
499 int i = 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)) {
503 result = i;
504 break;
505 } else {
506 aTitle = shrinkFilterName(aTitle).trim();
507 if (m_aCurrentFilter.equals(aTitle)) {
508 result = i;
509 break;
515 DBG_PRINT_EXIT(CLASS_NAME, __func__, result);
517 return result;
520 OUStringList FilterHelper::getCurrentFilterSuffixList() {
521 DBG_PRINT_ENTRY(CLASS_NAME, __func__);
523 OUStringList retVal;
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();
529 break;
530 } else {
531 aTitle = shrinkFilterName(aTitle).trim();
532 if (m_aCurrentFilter.equals(aTitle)) {
533 retVal = iter->getFilterSuffixList();
534 break;
540 DBG_PRINT_EXIT(CLASS_NAME, __func__);
542 return retVal;