xref: /AOO41X/main/fpicker/source/win32/filepicker/FilterContainer.cxx (revision b557fc96600fce3029f73c89748b6c08fd00b34d)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_fpicker.hxx"
26 
27 
28 #include <stdexcept>
29 #include <osl/diagnose.h>
30 #include "FilterContainer.hxx"
31 
32 #include <utility>
33 
34 #if defined _MSC_VER
35 #pragma warning(push, 1)
36 #endif
37 #include <windows.h>
38 #if defined _MSC_VER
39 #pragma warning(pop)
40 #endif
41 
42 //-------------------------------------------------------------------
43 // namespace directives
44 //-------------------------------------------------------------------
45 
46 using ::rtl::OUString;
47 
48 //-------------------------------------------------------------------------------------
49 // ctor
50 //-------------------------------------------------------------------------------------
51 
CFilterContainer(sal_Int32 initSize)52 CFilterContainer::CFilterContainer( sal_Int32 initSize ) :
53     m_vFilters( initSize ),
54     m_bIterInitialized( sal_False )
55 {
56 }
57 
58 //-----------------------------------------------------------------------------------------
59 // add a name/filter pair
60 //-----------------------------------------------------------------------------------------
61 
addFilter(const OUString & aName,const OUString & aFilter,sal_Bool bAllowDuplicates)62 sal_Bool SAL_CALL CFilterContainer::addFilter(
63     const OUString& aName, const OUString& aFilter, sal_Bool bAllowDuplicates )
64 {
65     // check if the filter is already in the container
66     sal_Int32 pos = -1;
67 
68     if ( !bAllowDuplicates )
69     {
70         pos = getFilterTagPos( aName );
71         if ( pos < 0 ) // if not there, append
72         {
73             m_vFilters.push_back( std::make_pair( aName, aFilter ) );
74             m_bIterInitialized = sal_False;
75         }
76     }
77     else
78     {
79         m_vFilters.push_back( std::make_pair( aName, aFilter ) );
80         m_bIterInitialized = sal_False;
81     }
82 
83     return ( pos < 0 ) ? sal_True : sal_False;
84 }
85 
86 //-----------------------------------------------------------------------------------------
87 // delete a filter
88 // Precondition: the container is not empty
89 //               there is a filter identified by the given name
90 //-----------------------------------------------------------------------------------------
91 
delFilter(const OUString & aName)92 sal_Bool SAL_CALL CFilterContainer::delFilter( const OUString& aName )
93 {
94     OSL_ASSERT( m_vFilters.size() > 0 );
95 
96     sal_Int32 pos = getFilterTagPos( aName );
97     if ( pos > -1 )
98     {
99         m_vFilters.erase( ( m_vFilters.begin() + pos ) );
100         m_bIterInitialized = sal_False;
101     }
102 
103     return ( pos > -1 ) ? sal_True : sal_False;
104 }
105 
106 //-----------------------------------------------------------------------------------------
107 // return the number of filters currently in the container
108 //-----------------------------------------------------------------------------------------
109 
numFilter()110 sal_Int32 SAL_CALL CFilterContainer::numFilter( )
111 {
112     return m_vFilters.size( );
113 }
114 
115 //-----------------------------------------------------------------------------------------
116 // clear all entries
117 //-----------------------------------------------------------------------------------------
118 
empty()119 void SAL_CALL CFilterContainer::empty()
120 {
121     m_vFilters.clear( );
122 }
123 
124 //-----------------------------------------------------------------------------------------
125 // get a filter by name
126 // Precondition: the container is not empty
127 //               there is a filter identified by the name
128 //-----------------------------------------------------------------------------------------
129 
getFilter(const OUString & aName,OUString & theFilter) const130 sal_Bool SAL_CALL CFilterContainer::getFilter( const OUString& aName, OUString& theFilter ) const
131 {
132     OSL_PRECOND( m_vFilters.size() > 0, "Empty filter container" );
133 
134     sal_Int32 pos = getFilterTagPos( aName );
135 
136     try
137     {
138         if ( pos > -1 )
139             theFilter = m_vFilters.at( pos ).second;
140     }
141     catch( std::out_of_range& )
142     {
143         OSL_ENSURE( sal_False, "Filter not in filter container" );
144         pos = -1;
145     }
146 
147     return (pos > -1 ) ? sal_True : sal_False;
148 }
149 
150 //-----------------------------------------------------------------------------------------
151 //
152 //-----------------------------------------------------------------------------------------
153 
getFilter(sal_Int32 aIndex,OUString & theFilter) const154 sal_Bool SAL_CALL CFilterContainer::getFilter( sal_Int32 aIndex, OUString& theFilter ) const
155 {
156     sal_Bool bRet = sal_True;
157 
158     try
159     {
160         theFilter = m_vFilters.at( aIndex ).first;
161     }
162     catch( std::out_of_range& )
163     {
164         OSL_ENSURE( sal_False, "Filter index out of range" );
165         bRet = sal_False;
166     }
167 
168     return bRet;
169 }
170 
171 //-----------------------------------------------------------------------------------------
172 //
173 //-----------------------------------------------------------------------------------------
174 
getFilterPos(const OUString & aName) const175 sal_Int32 SAL_CALL CFilterContainer::getFilterPos( const OUString& aName ) const
176 {
177     return getFilterTagPos( aName );
178 }
179 
180 //-----------------------------------------------------------------------------------------
181 // returns the index of the filter identified by name
182 //-----------------------------------------------------------------------------------------
183 
getFilterTagPos(const OUString & aName) const184 sal_Int32 SAL_CALL CFilterContainer::getFilterTagPos( const OUString& aName ) const
185 {
186     if ( m_vFilters.size( ) > 0 )
187     {
188         sal_Int32 i = 0;
189         FILTER_VECTOR_T::const_iterator iter;
190         FILTER_VECTOR_T::const_iterator iter_end = m_vFilters.end( );
191 
192         for ( iter = m_vFilters.begin( ); iter != iter_end; ++iter, ++i )
193             if ( ( *iter ).first.equalsIgnoreAsciiCase( aName ) )
194                 return i;
195     }
196 
197     return -1;
198 }
199 
200 //-----------------------------------------------------------------------------------------
201 // starts enumerating the filter in the container
202 //-----------------------------------------------------------------------------------------
203 
beginEnumFilter()204 void SAL_CALL CFilterContainer::beginEnumFilter( )
205 {
206     m_iter = m_vFilters.begin( );
207     m_bIterInitialized = sal_True;
208 }
209 
210 //-----------------------------------------------------------------------------------------
211 // returns true if another filter has been retrieved
212 //-----------------------------------------------------------------------------------------
213 
getNextFilter(FILTER_ENTRY_T & nextFilterEntry)214 sal_Bool SAL_CALL CFilterContainer::getNextFilter( FILTER_ENTRY_T& nextFilterEntry )
215 {
216     OSL_ASSERT( m_bIterInitialized );
217 
218     sal_Bool bRet = ( m_iter != m_vFilters.end( ) );
219 
220     if ( bRet )
221         nextFilterEntry = *m_iter++;
222     else
223         m_bIterInitialized = sal_False;
224 
225     return bRet;
226 }
227 
228 //-----------------------------------------------------------------------------------------
setCurrentFilter(const::rtl::OUString & aName)229 void SAL_CALL CFilterContainer::setCurrentFilter( const ::rtl::OUString& aName )
230 {
231     m_sCurrentFilter = aName;
232 }
233 
234 //-----------------------------------------------------------------------------------------
getCurrentFilter() const235 ::rtl::OUString SAL_CALL CFilterContainer::getCurrentFilter() const
236 {
237     return m_sCurrentFilter;
238 }
239 
240 //###################################################################
241 
242 
243 //-------------------------------------------------------------------
244 // calculates the length of a '\0' separated filter, that means
245 // length of the name + '\0' + length of the filter string +
246 // a trailing '\0'
247 //-------------------------------------------------------------------
248 
_getLengthFilter(CFilterContainer::FILTER_ENTRY_T aFilterEntry)249 static sal_uInt32 _getLengthFilter( CFilterContainer::FILTER_ENTRY_T aFilterEntry )
250 {
251     return (
252         aFilterEntry.first.getLength( )  + 1 +
253         aFilterEntry.second.getLength( ) + 1 );
254 }
255 
256 //-------------------------------------------------------------------
257 // calculates the length of all filters currently in the container
258 //-------------------------------------------------------------------
259 
_getTotalFilterLength(CFilterContainer & aFilterContainer)260 static sal_uInt32 _getTotalFilterLength( CFilterContainer& aFilterContainer )
261 {
262     CFilterContainer::FILTER_ENTRY_T nextFilter;
263 
264     aFilterContainer.beginEnumFilter( );
265 
266     sal_uInt32 totalLength = 0;
267     while( aFilterContainer.getNextFilter( nextFilter ) )
268         totalLength += _getLengthFilter( nextFilter );
269 
270     return ( totalLength > 0 ) ? totalLength + 1 : totalLength;
271 }
272 
273 //-------------------------------------------------------------------
274 //
275 //-------------------------------------------------------------------
276 
277 inline
_wcsmemcpy(sal_Unicode * pDest,const sal_Unicode * pSrc,sal_uInt32 nLength)278 void _wcsmemcpy( sal_Unicode* pDest, const sal_Unicode* pSrc, sal_uInt32 nLength )
279 {
280     memcpy( pDest, pSrc, nLength * sizeof( sal_Unicode ) );
281 }
282 
283 //-------------------------------------------------------------------
284 // a helper trivial helper function to create a filter buffer in the
285 // format the Win32 API requires,
286 // e.g. "Text\0*.txt\0Doc\0*.doc;*xls\0\0"
287 //-------------------------------------------------------------------
288 
makeWinFilterBuffer(CFilterContainer & aFilterContainer)289 rtl::OUString SAL_CALL makeWinFilterBuffer( CFilterContainer& aFilterContainer )
290 {
291     // calculate the required buffer size
292     sal_uInt32 reqBuffSize = _getTotalFilterLength( aFilterContainer );
293 
294     // return if there are no filters
295     if ( !reqBuffSize )
296         return OUString( );
297 
298     sal_Unicode* pBuff = new sal_Unicode[reqBuffSize];
299 
300     // initialize the buffer with 0
301     ZeroMemory( pBuff, sizeof( sal_Unicode ) * reqBuffSize );
302 
303     OUString winFilterBuff;
304     CFilterContainer::FILTER_ENTRY_T nextFilter;
305     sal_uInt32 memPos = 0;
306 
307     aFilterContainer.beginEnumFilter( );
308 
309     while( aFilterContainer.getNextFilter( nextFilter ) )
310     {
311         _wcsmemcpy(
312             pBuff + memPos,
313             nextFilter.first.getStr( ),
314             nextFilter.first.getLength( ) );
315 
316         memPos += nextFilter.first.getLength( ) + 1;
317 
318         _wcsmemcpy(
319             pBuff + memPos,
320             nextFilter.second.getStr( ),
321             nextFilter.second.getLength( ) );
322 
323         memPos += nextFilter.second.getLength( ) + 1 ;
324     }
325 
326     winFilterBuff = OUString( pBuff, reqBuffSize );
327 
328     // remove the allocated buffer
329     delete [] pBuff;
330 
331     return winFilterBuff;
332 }
333 
334