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