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