LibreOffice Module fpicker (master) 1
FilterContainer.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <sal/config.h>
21
22#include <algorithm>
23#include <memory>
24#include <stdexcept>
25#include <osl/diagnose.h>
26#include "FilterContainer.hxx"
27
28#include <utility>
29
30#if !defined WIN32_LEAN_AND_MEAN
31# define WIN32_LEAN_AND_MEAN
32#endif
33#include <windows.h>
34
36 m_vFilters( initSize ),
37 m_bIterInitialized( false )
38{
39}
40
41// add a name/filter pair
42
44 const OUString& aName, const OUString& aFilter, bool bAllowDuplicates )
45{
46 // check if the filter is already in the container
47 sal_Int32 pos = -1;
48
49 if ( !bAllowDuplicates )
50 {
52 if ( pos < 0 ) // if not there, append
53 {
54 m_vFilters.push_back( std::make_pair( aName, aFilter ) );
55 m_bIterInitialized = false;
56 }
57 }
58 else
59 {
60 m_vFilters.push_back( std::make_pair( aName, aFilter ) );
61 m_bIterInitialized = false;
62 }
63
64 return pos < 0;
65}
66
67// delete a filter
68// Precondition: the container is not empty
69// there is a filter identified by the given name
70
71bool CFilterContainer::delFilter( const OUString& aName )
72{
73 OSL_ASSERT( !m_vFilters.empty() );
74
75 sal_Int32 pos = getFilterTagPos( aName );
76 if ( pos > -1 )
77 {
78 m_vFilters.erase( m_vFilters.begin() + pos );
79 m_bIterInitialized = false;
80 }
81
82 return pos > -1;
83}
84
85// return the number of filters currently in the container
86
88{
89 return m_vFilters.size( );
90}
91
92// clear all entries
93
95{
96 m_vFilters.clear( );
97}
98
99// get a filter by name
100// Precondition: the container is not empty
101// there is a filter identified by the name
102
103bool CFilterContainer::getFilterByName(const OUString& aName, OUString& theFilter) const
104{
105 OSL_PRECOND( !m_vFilters.empty() , "Empty filter container" );
106 return getFilterByIndex(getFilterTagPos(aName), theFilter);
107}
108
109bool CFilterContainer::getFilterByIndex(sal_Int32 aIndex, OUString& theFilter) const
110{
111 bool bRet = true;
112
113 try
114 {
115 theFilter = m_vFilters.at(aIndex).second;
116 }
117 catch (std::out_of_range&)
118 {
119 OSL_FAIL("Filter index out of range");
120 bRet = false;
121 }
122
123 return bRet;
124}
125
126bool CFilterContainer::getFilterNameByIndex(sal_Int32 aIndex, OUString& theName) const
127{
128 bool bRet = true;
129
130 try
131 {
132 theName = m_vFilters.at(aIndex).first;
133 }
134 catch( std::out_of_range& )
135 {
136 OSL_FAIL( "Filter index out of range" );
137 bRet = false;
138 }
139
140 return bRet;
141}
142
143sal_Int32 CFilterContainer::getFilterPos( const OUString& aName ) const
144{
145 return getFilterTagPos( aName );
146}
147
148// returns the index of the filter identified by name
149
150sal_Int32 CFilterContainer::getFilterTagPos( const OUString& aName ) const
151{
152 if ( !m_vFilters.empty() )
153 {
154 FILTER_VECTOR_T::const_iterator iter = std::find_if(m_vFilters.begin(), m_vFilters.end(),
155 [&aName](const FILTER_ENTRY_T& rFilter) { return rFilter.first.equalsIgnoreAsciiCase(aName); });
156 if (iter != m_vFilters.end())
157 return std::distance(m_vFilters.begin(), iter);
158 }
159
160 return -1;
161}
162
163// starts enumerating the filter in the container
164
166{
167 m_iter = m_vFilters.begin( );
168 m_bIterInitialized = true;
169}
170
171// returns true if another filter has been retrieved
172
174{
175 OSL_ASSERT( m_bIterInitialized );
176
177 bool bRet = ( m_iter != m_vFilters.end( ) );
178
179 if ( bRet )
180 nextFilterEntry = *m_iter++;
181 else
182 m_bIterInitialized = false;
183
184 return bRet;
185}
186
187void CFilterContainer::setCurrentFilter( const OUString& aName )
188{
190}
191
193{
194 return m_sCurrentFilter;
195}
196
197// calculates the length of a '\0' separated filter, that means
198// length of the name + '\0' + length of the filter string +
199// a trailing '\0'
200
201static sal_uInt32 getLengthFilter( CFilterContainer::FILTER_ENTRY_T aFilterEntry )
202{
203 return (
204 aFilterEntry.first.getLength( ) + 1 +
205 aFilterEntry.second.getLength( ) + 1 );
206}
207
208// calculates the length of all filters currently in the container
209
210static sal_uInt32 getTotalFilterLength( CFilterContainer& aFilterContainer )
211{
213
214 aFilterContainer.beginEnumFilter( );
215
216 sal_uInt32 totalLength = 0;
217 while( aFilterContainer.getNextFilter( nextFilter ) )
218 totalLength += getLengthFilter( nextFilter );
219
220 return ( totalLength > 0 ) ? totalLength + 1 : totalLength;
221}
222
223static
224void wcsmemcpy( sal_Unicode* pDest, const sal_Unicode* pSrc, sal_uInt32 nLength )
225{
226 memcpy( pDest, pSrc, nLength * sizeof( sal_Unicode ) );
227}
228
229// a helper trivial helper function to create a filter buffer in the
230// format the Win32 API requires,
231// e.g. "Text\0*.txt\0Doc\0*.doc;*xls\0\0"
232
233OUString makeWinFilterBuffer( CFilterContainer& aFilterContainer )
234{
235 // calculate the required buffer size
236 sal_uInt32 reqBuffSize = getTotalFilterLength( aFilterContainer );
237
238 // return if there are no filters
239 if ( !reqBuffSize )
240 return OUString( );
241
242 auto pBuff = std::make_unique<sal_Unicode[]>(reqBuffSize);
243
244 // initialize the buffer with 0
245 ZeroMemory( pBuff.get(), sizeof( sal_Unicode ) * reqBuffSize );
246
247 OUString winFilterBuff;
249 sal_uInt32 memPos = 0;
250
251 aFilterContainer.beginEnumFilter( );
252
253 while( aFilterContainer.getNextFilter( nextFilter ) )
254 {
255 wcsmemcpy(
256 pBuff.get() + memPos,
257 nextFilter.first.getStr( ),
258 nextFilter.first.getLength( ) );
259
260 memPos += nextFilter.first.getLength( ) + 1;
261
262 wcsmemcpy(
263 pBuff.get() + memPos,
264 nextFilter.second.getStr( ),
265 nextFilter.second.getLength( ) );
266
267 memPos += nextFilter.second.getLength( ) + 1 ;
268 }
269
270 winFilterBuff = OUString( pBuff.get(), reqBuffSize );
271
272 return winFilterBuff;
273}
274
275/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static sal_uInt32 getLengthFilter(CFilterContainer::FILTER_ENTRY_T aFilterEntry)
static sal_uInt32 getTotalFilterLength(CFilterContainer &aFilterContainer)
static void wcsmemcpy(sal_Unicode *pDest, const sal_Unicode *pSrc, sal_uInt32 nLength)
OUString makeWinFilterBuffer(CFilterContainer &aFilterContainer)
bool getFilterByIndex(sal_Int32 aIndex, OUString &theFilter) const
void setCurrentFilter(const OUString &aName)
std::pair< OUString, OUString > FILTER_ENTRY_T
bool getFilterByName(const OUString &aName, OUString &theFilter) const
CFilterContainer(sal_Int32 initSize=0)
sal_Int32 getFilterTagPos(const OUString &aName) const
sal_Int32 numFilter()
OUString getCurrentFilter() const
FILTER_VECTOR_T m_vFilters
sal_Int32 getFilterPos(const OUString &aName) const
bool getFilterNameByIndex(sal_Int32 aIndex, OUString &theName) const
FILTER_VECTOR_T::const_iterator m_iter
bool getNextFilter(FILTER_ENTRY_T &nextFilterEntry)
bool addFilter(const OUString &aName, const OUString &aFilter, bool bAllowDuplicates=false)
bool delFilter(const OUString &aName)
std::deque< AttacherIndex_Impl > aIndex
OUString aName
sal_uInt16 sal_Unicode
size_t pos
sal_Int32 nLength