merge the formfield patch from ooo-build
[ooovba.git] / dtrans / source / win32 / dtobj / FetcList.cxx
blob0c468ae13bb654d1a7b381419dc2f215df2bb580
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: FetcList.cxx,v $
10 * $Revision: 1.18 $
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 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_dtrans.hxx"
34 //------------------------------------------------------------------------
35 // includes
36 //------------------------------------------------------------------------
37 #include <osl/diagnose.h>
38 #include "FetcList.hxx"
39 #include "Fetc.hxx"
40 #include <com/sun/star/datatransfer/XMimeContentTypeFactory.hpp>
41 #include <com/sun/star/datatransfer/XMimeContentType.hpp>
43 #ifndef _DATAFORMATTRANSLATOR_HXX_
44 #include "DataFmtTransl.hxx"
45 #endif
46 #include "..\misc\ImplHelper.hxx"
47 #include "..\misc\WinClip.hxx"
49 #include <algorithm>
51 #include "MimeAttrib.hxx"
53 //------------------------------------------------------------------------
54 // namespace directives
55 //------------------------------------------------------------------------
57 using namespace com::sun::star::uno;
58 using namespace com::sun::star::datatransfer;
59 using namespace com::sun::star::lang;
60 using namespace com::sun::star::container;
61 using namespace rtl;
62 using namespace std;
64 //------------------------------------------------------------------------
65 //
66 //------------------------------------------------------------------------
68 LCID CFormatRegistrar::m_TxtLocale = 0;
69 sal_uInt32 CFormatRegistrar::m_TxtCodePage = GetACP( );
71 //------------------------------------------------------------------------
72 //
73 //------------------------------------------------------------------------
75 CFormatEtcContainer::CFormatEtcContainer( )
77 m_EnumIterator = m_FormatMap.begin( );
80 //------------------------------------------------------------------------
81 //
82 //------------------------------------------------------------------------
84 void CFormatEtcContainer::addFormatEtc( const CFormatEtc& fetc )
86 m_FormatMap.push_back( CFormatEtc( fetc ) );
89 //------------------------------------------------------------------------
90 //
91 //------------------------------------------------------------------------
93 void SAL_CALL CFormatEtcContainer::removeFormatEtc( const CFormatEtc& fetc )
95 FormatEtcMap_t::iterator iter =
96 find( m_FormatMap.begin(), m_FormatMap.end(), fetc );
98 if ( iter != m_FormatMap.end( ) )
99 m_FormatMap.erase( iter );
102 //------------------------------------------------------------------------
104 //------------------------------------------------------------------------
106 void SAL_CALL CFormatEtcContainer::removeAllFormatEtc( )
108 m_FormatMap.clear( );
111 //------------------------------------------------------------------------
113 //------------------------------------------------------------------------
115 sal_Bool CFormatEtcContainer::hasFormatEtc( const CFormatEtc& fetc ) const
117 FormatEtcMap_t::const_iterator iter =
118 find( m_FormatMap.begin(), m_FormatMap.end(), fetc );
120 return ( iter != m_FormatMap.end( ) );
123 //------------------------------------------------------------------------
125 //------------------------------------------------------------------------
127 sal_Bool CFormatEtcContainer::hasElements( ) const
129 return ( m_FormatMap.size( ) > 0 );
132 //------------------------------------------------------------------------
134 //------------------------------------------------------------------------
136 void CFormatEtcContainer::beginEnumFormatEtc( )
138 m_EnumIterator = m_FormatMap.begin( );
141 //------------------------------------------------------------------------
143 //------------------------------------------------------------------------
145 sal_uInt32 SAL_CALL CFormatEtcContainer::nextFormatEtc( LPFORMATETC lpFetc,
146 sal_uInt32 aNum )
148 OSL_ASSERT( lpFetc );
149 OSL_ASSERT( !IsBadWritePtr( lpFetc, sizeof( FORMATETC ) * aNum ) );
151 sal_uInt32 nFetched = 0;
153 if ( m_EnumIterator != m_FormatMap.end( ) )
155 for ( sal_uInt32 i = 0; i < aNum; i++, nFetched++, lpFetc++, ++m_EnumIterator )
156 CopyFormatEtc( lpFetc, *m_EnumIterator );
159 return nFetched;
163 //------------------------------------------------------------------------
165 //------------------------------------------------------------------------
167 sal_Bool SAL_CALL CFormatEtcContainer::skipFormatEtc( sal_uInt32 aNum )
169 FormatEtcMap_t::const_iterator iter_end = m_FormatMap.end( );
170 for ( sal_uInt32 i = 0;
171 (i < aNum) && (m_EnumIterator != iter_end);
172 i++, ++m_EnumIterator )
173 ;/* intentionally left empty */
175 return ( m_EnumIterator != m_FormatMap.end( ) );
179 //#########################################################################
182 //------------------------------------------------------------------------
184 //------------------------------------------------------------------------
186 CFormatRegistrar::CFormatRegistrar( const Reference< XMultiServiceFactory >& ServiceManager,
187 const CDataFormatTranslator& aDataFormatTranslator ) :
188 m_DataFormatTranslator( aDataFormatTranslator ),
189 m_bHasSynthesizedLocale( sal_False ),
190 m_SrvMgr( ServiceManager )
194 // ----------------------------------------------------------------------------------------
195 // this function converts all DataFlavors of the given FlavorList into
196 // an appropriate FORMATETC structure, for some formats like unicodetext,
197 // text and text/html we will offer an accompany format e.g.:
199 // DataFlavor | Registered Clipformat | Registered accompany clipformat
200 // -------------------------|---------------------------|-----------------------------------
201 // text/plain;charset=ansi | CF_TEXT | CF_UNICODETEXT
202 // | | CF_LOCALE (if charset != GetACP()
203 // | |
204 // text/plain;charset=oem | CF_OEMTEXT | CF_UNICODETEXT
205 // | | CF_LOCALE (if charset != GetOEMCP()
206 // | |
207 // text/plain;charset=utf-16| CF_UNICODETEXT | CF_TEXT
208 // | |
209 // text/html | HTML (Hypertext ...) | HTML Format
210 // | |
212 // if some tries to register different text formats with different charsets the last
213 // registered wins and the others are ignored
214 // ----------------------------------------------------------------------------------------
216 void SAL_CALL CFormatRegistrar::RegisterFormats(
217 const Reference< XTransferable >& aXTransferable, CFormatEtcContainer& aFormatEtcContainer )
219 Sequence< DataFlavor > aFlavorList = aXTransferable->getTransferDataFlavors( );
220 sal_Int32 nFlavors = aFlavorList.getLength( );
221 sal_Bool bUnicodeRegistered = sal_False;
222 DataFlavor aFlavor;
224 for( sal_Int32 i = 0; i < nFlavors; i++ )
226 aFlavor = aFlavorList[i];
227 CFormatEtc fetc = m_DataFormatTranslator.getFormatEtcFromDataFlavor( aFlavor );
229 // maybe an internal format so we ignore it
230 if ( CF_INVALID == fetc.getClipformat( ) )
231 continue;
233 if ( !needsToSynthesizeAccompanyFormats( fetc ) )
234 aFormatEtcContainer.addFormatEtc( fetc );
235 else
237 // if we haven't registered any text format up to now
238 if ( m_DataFormatTranslator.isTextFormat( fetc.getClipformat() ) && !bUnicodeRegistered )
240 // if the transferable supports unicode text we ignore
241 // any further text format the transferable offers
242 // because we can create it from Unicode text in addition
243 // we register CF_TEXT for non unicode clients
244 if ( m_DataFormatTranslator.isUnicodeTextFormat( fetc.getClipformat() ) )
246 aFormatEtcContainer.addFormatEtc( fetc ); // add CF_UNICODE
247 aFormatEtcContainer.addFormatEtc(
248 m_DataFormatTranslator.getFormatEtcForClipformat( CF_TEXT ) ); // add CF_TEXT
249 bUnicodeRegistered = sal_True;
251 else if ( !hasUnicodeFlavor( aXTransferable ) )
253 // we try to investigate the charset and make a valid
254 // windows codepage from this charset the default
255 // return value is the result of GetACP( )
256 OUString charset = getCharsetFromDataFlavor( aFlavor );
257 sal_uInt32 txtCP = getWinCPFromMimeCharset( charset );
259 // we try to get a Locale appropriate for this codepage
260 if ( findLocaleForTextCodePage( ) )
262 m_TxtCodePage = txtCP;
264 aFormatEtcContainer.addFormatEtc(
265 m_DataFormatTranslator.getFormatEtcForClipformat( CF_UNICODETEXT ) );
267 if ( !IsOEMCP( m_TxtCodePage ) )
268 aFormatEtcContainer.addFormatEtc(
269 m_DataFormatTranslator.getFormatEtcForClipformat( CF_TEXT ) );
270 else
271 aFormatEtcContainer.addFormatEtc(
272 m_DataFormatTranslator.getFormatEtcForClipformat( CF_OEMTEXT ) );
274 aFormatEtcContainer.addFormatEtc(
275 m_DataFormatTranslator.getFormatEtcForClipformat( CF_LOCALE ) );
277 // we save the flavor so it's easier when
278 // queried for it in XTDataObject::GetData(...)
279 m_RegisteredTextFlavor = aFlavor;
280 m_bHasSynthesizedLocale = sal_True;
284 else if ( m_DataFormatTranslator.isTextHtmlFormat( fetc.getClipformat( ) ) ) // Html (Hyper Text...)
286 // we add text/html ( HTML (HyperText Markup Language) )
287 aFormatEtcContainer.addFormatEtc( fetc );
289 // and HTML Format
290 OUString htmlFormat( OUString::createFromAscii( "HTML Format" ) );
291 aFormatEtcContainer.addFormatEtc(
292 m_DataFormatTranslator.getFormatEtcForClipformatName( htmlFormat ) );
298 //------------------------------------------------------------------------
300 //------------------------------------------------------------------------
302 sal_Bool SAL_CALL CFormatRegistrar::hasSynthesizedLocale( ) const
304 return m_bHasSynthesizedLocale;
307 //------------------------------------------------------------------------
309 //------------------------------------------------------------------------
311 LCID SAL_CALL CFormatRegistrar::getSynthesizedLocale( ) const
313 return m_TxtLocale;
316 //------------------------------------------------------------------------
318 //------------------------------------------------------------------------
320 sal_uInt32 SAL_CALL CFormatRegistrar::getRegisteredTextCodePage( ) const
322 return m_TxtCodePage;
325 //------------------------------------------------------------------------
327 //------------------------------------------------------------------------
329 DataFlavor SAL_CALL CFormatRegistrar::getRegisteredTextFlavor( ) const
331 return m_RegisteredTextFlavor;
334 //------------------------------------------------------------------------
336 //------------------------------------------------------------------------
338 sal_Bool SAL_CALL CFormatRegistrar::isSynthesizeableFormat( const CFormatEtc& aFormatEtc ) const
340 return ( m_DataFormatTranslator.isOemOrAnsiTextFormat( aFormatEtc.getClipformat() ) ||
341 m_DataFormatTranslator.isUnicodeTextFormat( aFormatEtc.getClipformat() ) ||
342 m_DataFormatTranslator.isHTMLFormat( aFormatEtc.getClipformat() ) );
345 //------------------------------------------------------------------------
347 //------------------------------------------------------------------------
349 inline
350 sal_Bool SAL_CALL CFormatRegistrar::needsToSynthesizeAccompanyFormats( const CFormatEtc& aFormatEtc ) const
352 return ( m_DataFormatTranslator.isOemOrAnsiTextFormat( aFormatEtc.getClipformat() ) ||
353 m_DataFormatTranslator.isUnicodeTextFormat( aFormatEtc.getClipformat() ) ||
354 m_DataFormatTranslator.isTextHtmlFormat( aFormatEtc.getClipformat( ) ) );
357 //------------------------------------------------------------------------
359 //------------------------------------------------------------------------
361 OUString SAL_CALL CFormatRegistrar::getCharsetFromDataFlavor( const DataFlavor& aFlavor )
363 OUString charset;
367 Reference< XMimeContentTypeFactory > xMimeFac(
368 m_SrvMgr->createInstance( OUString::createFromAscii( \
369 "com.sun.star.datatransfer.MimeContentTypeFactory" ) ), UNO_QUERY );
371 if( xMimeFac.is( ) )
373 Reference< XMimeContentType > xMimeType( xMimeFac->createMimeContentType( aFlavor.MimeType ) );
374 if ( xMimeType->hasParameter( TEXTPLAIN_PARAM_CHARSET ) )
375 charset = xMimeType->getParameterValue( TEXTPLAIN_PARAM_CHARSET );
376 else
377 charset = getMimeCharsetFromWinCP( GetACP( ), PRE_WINDOWS_CODEPAGE );
380 catch(NoSuchElementException&)
382 OSL_ENSURE( sal_False, "Unexpected" );
384 catch(...)
386 OSL_ENSURE( sal_False, "Invalid data flavor" );
389 return charset;
392 //------------------------------------------------------------------------
394 //------------------------------------------------------------------------
396 sal_Bool SAL_CALL CFormatRegistrar::hasUnicodeFlavor( const Reference< XTransferable >& aXTransferable ) const
398 CFormatEtc fetc( CF_UNICODETEXT );
400 DataFlavor aFlavor =
401 m_DataFormatTranslator.getDataFlavorFromFormatEtc( fetc );
403 return aXTransferable->isDataFlavorSupported( aFlavor );
406 //------------------------------------------------------------------------
408 //------------------------------------------------------------------------
410 inline
411 sal_Bool CFormatRegistrar::isEqualCurrentSystemCodePage( sal_uInt32 aCodePage ) const
413 return ( (aCodePage == GetOEMCP()) || (aCodePage == GetACP()) );
416 //------------------------------------------------------------------------
418 //------------------------------------------------------------------------
420 sal_Bool SAL_CALL CFormatRegistrar::findLocaleForTextCodePage( )
422 m_TxtLocale = 0;
423 EnumSystemLocalesA( CFormatRegistrar::EnumLocalesProc, LCID_INSTALLED );
424 return ( IsValidLocale( m_TxtLocale, LCID_INSTALLED ) ) ? sal_True : sal_False;
427 //------------------------------------------------------------------------
429 //------------------------------------------------------------------------
431 sal_Bool SAL_CALL CFormatRegistrar::isLocaleCodePage( LCID lcid, LCTYPE lctype, sal_uInt32 codepage )
433 char buff[6];
434 sal_uInt32 localeCodePage;
436 OSL_ASSERT( IsValidLocale( lcid, LCID_INSTALLED ) );
438 // get the ansi codepage of the current locale
439 GetLocaleInfoA( lcid, lctype, buff, sizeof( buff ) );
440 localeCodePage = atol( buff );
442 return ( localeCodePage == codepage );
445 //------------------------------------------------------------------------
447 //------------------------------------------------------------------------
449 inline
450 sal_Bool SAL_CALL CFormatRegistrar::isLocaleOemCodePage( LCID lcid, sal_uInt32 codepage )
452 return isLocaleCodePage( lcid, LOCALE_IDEFAULTCODEPAGE, codepage );
455 //------------------------------------------------------------------------
457 //------------------------------------------------------------------------
459 inline
460 sal_Bool SAL_CALL CFormatRegistrar::isLocaleAnsiCodePage( LCID lcid, sal_uInt32 codepage )
462 return isLocaleCodePage( lcid, LOCALE_IDEFAULTANSICODEPAGE, codepage );
465 //------------------------------------------------------------------------
467 //------------------------------------------------------------------------
469 BOOL CALLBACK CFormatRegistrar::EnumLocalesProc( LPSTR lpLocaleStr )
471 // the lpLocaleStr parametere is hexadecimal
472 LCID lcid = strtol( lpLocaleStr, NULL, 16 );
474 if ( isLocaleAnsiCodePage( lcid, CFormatRegistrar::m_TxtCodePage ) ||
475 isLocaleOemCodePage( lcid, CFormatRegistrar::m_TxtCodePage ) )
477 CFormatRegistrar::m_TxtLocale = lcid;
478 return sal_False; // stop enumerating
481 return sal_True;