1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: FetcList.cxx,v $
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 //------------------------------------------------------------------------
36 //------------------------------------------------------------------------
37 #include <osl/diagnose.h>
38 #include "FetcList.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"
46 #include "..\misc\ImplHelper.hxx"
47 #include "..\misc\WinClip.hxx"
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
;
64 //------------------------------------------------------------------------
66 //------------------------------------------------------------------------
68 LCID
CFormatRegistrar::m_TxtLocale
= 0;
69 sal_uInt32
CFormatRegistrar::m_TxtCodePage
= GetACP( );
71 //------------------------------------------------------------------------
73 //------------------------------------------------------------------------
75 CFormatEtcContainer::CFormatEtcContainer( )
77 m_EnumIterator
= m_FormatMap
.begin( );
80 //------------------------------------------------------------------------
82 //------------------------------------------------------------------------
84 void CFormatEtcContainer::addFormatEtc( const CFormatEtc
& fetc
)
86 m_FormatMap
.push_back( CFormatEtc( fetc
) );
89 //------------------------------------------------------------------------
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
,
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
);
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()
204 // text/plain;charset=oem | CF_OEMTEXT | CF_UNICODETEXT
205 // | | CF_LOCALE (if charset != GetOEMCP()
207 // text/plain;charset=utf-16| CF_UNICODETEXT | CF_TEXT
209 // text/html | HTML (Hypertext ...) | HTML Format
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
;
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( ) )
233 if ( !needsToSynthesizeAccompanyFormats( fetc
) )
234 aFormatEtcContainer
.addFormatEtc( fetc
);
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
) );
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
);
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
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 //------------------------------------------------------------------------
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
)
367 Reference
< XMimeContentTypeFactory
> xMimeFac(
368 m_SrvMgr
->createInstance( OUString::createFromAscii( \
369 "com.sun.star.datatransfer.MimeContentTypeFactory" ) ), UNO_QUERY
);
373 Reference
< XMimeContentType
> xMimeType( xMimeFac
->createMimeContentType( aFlavor
.MimeType
) );
374 if ( xMimeType
->hasParameter( TEXTPLAIN_PARAM_CHARSET
) )
375 charset
= xMimeType
->getParameterValue( TEXTPLAIN_PARAM_CHARSET
);
377 charset
= getMimeCharsetFromWinCP( GetACP( ), PRE_WINDOWS_CODEPAGE
);
380 catch(NoSuchElementException
&)
382 OSL_ENSURE( sal_False
, "Unexpected" );
386 OSL_ENSURE( sal_False
, "Invalid data flavor" );
392 //------------------------------------------------------------------------
394 //------------------------------------------------------------------------
396 sal_Bool SAL_CALL
CFormatRegistrar::hasUnicodeFlavor( const Reference
< XTransferable
>& aXTransferable
) const
398 CFormatEtc
fetc( CF_UNICODETEXT
);
401 m_DataFormatTranslator
.getDataFlavorFromFormatEtc( fetc
);
403 return aXTransferable
->isDataFlavorSupported( aFlavor
);
406 //------------------------------------------------------------------------
408 //------------------------------------------------------------------------
411 sal_Bool
CFormatRegistrar::isEqualCurrentSystemCodePage( sal_uInt32 aCodePage
) const
413 return ( (aCodePage
== GetOEMCP()) || (aCodePage
== GetACP()) );
416 //------------------------------------------------------------------------
418 //------------------------------------------------------------------------
420 sal_Bool SAL_CALL
CFormatRegistrar::findLocaleForTextCodePage( )
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
)
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 //------------------------------------------------------------------------
450 sal_Bool SAL_CALL
CFormatRegistrar::isLocaleOemCodePage( LCID lcid
, sal_uInt32 codepage
)
452 return isLocaleCodePage( lcid
, LOCALE_IDEFAULTCODEPAGE
, codepage
);
455 //------------------------------------------------------------------------
457 //------------------------------------------------------------------------
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