Branch libreoffice-5-0-4
[LibreOffice.git] / dtrans / source / win32 / dtobj / FetcList.cxx
blob7eba9fd20cd80492fbe8d27ecfb06f9d1a097de1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <osl/diagnose.h>
21 #include "FetcList.hxx"
22 #include "Fetc.hxx"
23 #include <com/sun/star/datatransfer/MimeContentTypeFactory.hpp>
24 #include <com/sun/star/datatransfer/XMimeContentType.hpp>
26 #include "DataFmtTransl.hxx"
27 #include "../misc/ImplHelper.hxx"
28 #include "../misc/WinClip.hxx"
30 #include <algorithm>
32 #include "MimeAttrib.hxx"
34 // namespace directives
36 using namespace com::sun::star::uno;
37 using namespace com::sun::star::datatransfer;
38 using namespace com::sun::star::lang;
39 using namespace com::sun::star::container;
40 using namespace std;
42 LCID CFormatRegistrar::m_TxtLocale = 0;
43 sal_uInt32 CFormatRegistrar::m_TxtCodePage = GetACP( );
45 CFormatEtcContainer::CFormatEtcContainer( )
47 m_EnumIterator = m_FormatMap.begin( );
50 void CFormatEtcContainer::addFormatEtc( const CFormatEtc& fetc )
52 m_FormatMap.push_back( CFormatEtc( fetc ) );
55 void SAL_CALL CFormatEtcContainer::removeFormatEtc( const CFormatEtc& fetc )
57 FormatEtcMap_t::iterator iter =
58 find( m_FormatMap.begin(), m_FormatMap.end(), fetc );
60 if ( iter != m_FormatMap.end( ) )
61 m_FormatMap.erase( iter );
64 void SAL_CALL CFormatEtcContainer::removeAllFormatEtc( )
66 m_FormatMap.clear( );
69 sal_Bool CFormatEtcContainer::hasFormatEtc( const CFormatEtc& fetc ) const
71 FormatEtcMap_t::const_iterator iter =
72 find( m_FormatMap.begin(), m_FormatMap.end(), fetc );
74 return ( iter != m_FormatMap.end( ) );
77 sal_Bool CFormatEtcContainer::hasElements( ) const
79 return !m_FormatMap.empty();
82 void CFormatEtcContainer::beginEnumFormatEtc( )
84 m_EnumIterator = m_FormatMap.begin( );
87 sal_uInt32 SAL_CALL CFormatEtcContainer::nextFormatEtc( LPFORMATETC lpFetc,
88 sal_uInt32 aNum )
90 OSL_ASSERT( lpFetc );
91 OSL_ASSERT( !IsBadWritePtr( lpFetc, sizeof( FORMATETC ) * aNum ) );
93 sal_uInt32 nFetched = 0;
95 for ( sal_uInt32 i = 0; i < aNum; i++, nFetched++, lpFetc++, ++m_EnumIterator )
97 if ( m_EnumIterator == m_FormatMap.end() )
98 break;
99 CopyFormatEtc( lpFetc, *m_EnumIterator );
102 return nFetched;
105 sal_Bool SAL_CALL CFormatEtcContainer::skipFormatEtc( sal_uInt32 aNum )
107 FormatEtcMap_t::const_iterator iter_end = m_FormatMap.end( );
108 for ( sal_uInt32 i = 0;
109 (i < aNum) && (m_EnumIterator != iter_end);
110 i++, ++m_EnumIterator )
111 ;/* intentionally left empty */
113 return ( m_EnumIterator != m_FormatMap.end( ) );
116 CFormatRegistrar::CFormatRegistrar( const Reference< XComponentContext >& rxContext,
117 const CDataFormatTranslator& aDataFormatTranslator ) :
118 m_DataFormatTranslator( aDataFormatTranslator ),
119 m_bHasSynthesizedLocale( sal_False ),
120 m_xContext( rxContext )
124 // this function converts all DataFlavors of the given FlavorList into
125 // an appropriate FORMATETC structure, for some formats like unicodetext,
126 // text and text/html we will offer an accompany format e.g.:
128 // DataFlavor | Registered Clipformat | Registered accompany clipformat
129 // -------------------------|---------------------------|-----------------------------------
130 // text/plain;charset=ansi | CF_TEXT | CF_UNICODETEXT
131 // | | CF_LOCALE (if charset != GetACP()
132 // | |
133 // text/plain;charset=oem | CF_OEMTEXT | CF_UNICODETEXT
134 // | | CF_LOCALE (if charset != GetOEMCP()
135 // | |
136 // text/plain;charset=utf-16| CF_UNICODETEXT | CF_TEXT
137 // | |
138 // text/html | HTML (Hypertext ...) | HTML Format
139 // | |
141 // if some tries to register different text formats with different charsets the last
142 // registered wins and the others are ignored
144 void SAL_CALL CFormatRegistrar::RegisterFormats(
145 const Reference< XTransferable >& aXTransferable, CFormatEtcContainer& aFormatEtcContainer )
147 Sequence< DataFlavor > aFlavorList = aXTransferable->getTransferDataFlavors( );
148 sal_Int32 nFlavors = aFlavorList.getLength( );
149 sal_Bool bUnicodeRegistered = sal_False;
150 DataFlavor aFlavor;
152 for( sal_Int32 i = 0; i < nFlavors; i++ )
154 aFlavor = aFlavorList[i];
155 CFormatEtc fetc = m_DataFormatTranslator.getFormatEtcFromDataFlavor( aFlavor );
157 // maybe an internal format so we ignore it
158 if ( CF_INVALID == fetc.getClipformat( ) )
159 continue;
161 if ( !needsToSynthesizeAccompanyFormats( fetc ) )
162 aFormatEtcContainer.addFormatEtc( fetc );
163 else
165 // if we haven't registered any text format up to now
166 if ( m_DataFormatTranslator.isTextFormat( fetc.getClipformat() ) && !bUnicodeRegistered )
168 // if the transferable supports unicode text we ignore
169 // any further text format the transferable offers
170 // because we can create it from Unicode text in addition
171 // we register CF_TEXT for non unicode clients
172 if ( m_DataFormatTranslator.isUnicodeTextFormat( fetc.getClipformat() ) )
174 aFormatEtcContainer.addFormatEtc( fetc ); // add CF_UNICODE
175 aFormatEtcContainer.addFormatEtc(
176 m_DataFormatTranslator.getFormatEtcForClipformat( CF_TEXT ) ); // add CF_TEXT
177 bUnicodeRegistered = sal_True;
179 else if ( !hasUnicodeFlavor( aXTransferable ) )
181 // we try to investigate the charset and make a valid
182 // windows codepage from this charset the default
183 // return value is the result of GetACP( )
184 OUString charset = getCharsetFromDataFlavor( aFlavor );
185 sal_uInt32 txtCP = getWinCPFromMimeCharset( charset );
187 // we try to get a Locale appropriate for this codepage
188 if ( findLocaleForTextCodePage( ) )
190 m_TxtCodePage = txtCP;
192 aFormatEtcContainer.addFormatEtc(
193 m_DataFormatTranslator.getFormatEtcForClipformat( CF_UNICODETEXT ) );
195 if ( !IsOEMCP( m_TxtCodePage ) )
196 aFormatEtcContainer.addFormatEtc(
197 m_DataFormatTranslator.getFormatEtcForClipformat( CF_TEXT ) );
198 else
199 aFormatEtcContainer.addFormatEtc(
200 m_DataFormatTranslator.getFormatEtcForClipformat( CF_OEMTEXT ) );
202 aFormatEtcContainer.addFormatEtc(
203 m_DataFormatTranslator.getFormatEtcForClipformat( CF_LOCALE ) );
205 // we save the flavor so it's easier when
206 // queried for it in XTDataObject::GetData(...)
207 m_RegisteredTextFlavor = aFlavor;
208 m_bHasSynthesizedLocale = sal_True;
212 else if ( m_DataFormatTranslator.isTextHtmlFormat( fetc.getClipformat( ) ) ) // Html (Hyper Text...)
214 // we add text/html ( HTML (HyperText Markup Language) )
215 aFormatEtcContainer.addFormatEtc( fetc );
217 // and HTML Format
218 OUString htmlFormat( "HTML Format" );
219 aFormatEtcContainer.addFormatEtc(
220 m_DataFormatTranslator.getFormatEtcForClipformatName( htmlFormat ) );
226 sal_Bool SAL_CALL CFormatRegistrar::hasSynthesizedLocale( ) const
228 return m_bHasSynthesizedLocale;
231 LCID SAL_CALL CFormatRegistrar::getSynthesizedLocale( ) const
233 return m_TxtLocale;
236 sal_uInt32 SAL_CALL CFormatRegistrar::getRegisteredTextCodePage( ) const
238 return m_TxtCodePage;
241 DataFlavor SAL_CALL CFormatRegistrar::getRegisteredTextFlavor( ) const
243 return m_RegisteredTextFlavor;
246 sal_Bool SAL_CALL CFormatRegistrar::isSynthesizeableFormat( const CFormatEtc& aFormatEtc ) const
248 return ( m_DataFormatTranslator.isOemOrAnsiTextFormat( aFormatEtc.getClipformat() ) ||
249 m_DataFormatTranslator.isUnicodeTextFormat( aFormatEtc.getClipformat() ) ||
250 m_DataFormatTranslator.isHTMLFormat( aFormatEtc.getClipformat() ) );
253 inline
254 sal_Bool SAL_CALL CFormatRegistrar::needsToSynthesizeAccompanyFormats( const CFormatEtc& aFormatEtc ) const
256 return ( m_DataFormatTranslator.isOemOrAnsiTextFormat( aFormatEtc.getClipformat() ) ||
257 m_DataFormatTranslator.isUnicodeTextFormat( aFormatEtc.getClipformat() ) ||
258 m_DataFormatTranslator.isTextHtmlFormat( aFormatEtc.getClipformat( ) ) );
261 OUString SAL_CALL CFormatRegistrar::getCharsetFromDataFlavor( const DataFlavor& aFlavor )
263 OUString charset;
267 Reference< XMimeContentTypeFactory > xMimeFac =
268 MimeContentTypeFactory::create(m_xContext);
270 Reference< XMimeContentType > xMimeType( xMimeFac->createMimeContentType( aFlavor.MimeType ) );
271 if ( xMimeType->hasParameter( TEXTPLAIN_PARAM_CHARSET ) )
272 charset = xMimeType->getParameterValue( TEXTPLAIN_PARAM_CHARSET );
273 else
274 charset = getMimeCharsetFromWinCP( GetACP( ), PRE_WINDOWS_CODEPAGE );
276 catch(NoSuchElementException&)
278 OSL_FAIL( "Unexpected" );
280 catch(...)
282 OSL_FAIL( "Invalid data flavor" );
285 return charset;
288 sal_Bool SAL_CALL CFormatRegistrar::hasUnicodeFlavor( const Reference< XTransferable >& aXTransferable ) const
290 CFormatEtc fetc( CF_UNICODETEXT );
292 DataFlavor aFlavor =
293 m_DataFormatTranslator.getDataFlavorFromFormatEtc( fetc );
295 return aXTransferable->isDataFlavorSupported( aFlavor );
298 inline
299 sal_Bool CFormatRegistrar::isEqualCurrentSystemCodePage( sal_uInt32 aCodePage ) const
301 return ( (aCodePage == GetOEMCP()) || (aCodePage == GetACP()) );
304 sal_Bool SAL_CALL CFormatRegistrar::findLocaleForTextCodePage( )
306 m_TxtLocale = 0;
307 EnumSystemLocalesA( CFormatRegistrar::EnumLocalesProc, LCID_INSTALLED );
308 return ( IsValidLocale( m_TxtLocale, LCID_INSTALLED ) ) ? sal_True : sal_False;
311 sal_Bool SAL_CALL CFormatRegistrar::isLocaleCodePage( LCID lcid, LCTYPE lctype, sal_uInt32 codepage )
313 char buff[6];
314 sal_uInt32 localeCodePage;
316 OSL_ASSERT( IsValidLocale( lcid, LCID_INSTALLED ) );
318 // get the ansi codepage of the current locale
319 GetLocaleInfoA( lcid, lctype, buff, sizeof( buff ) );
320 localeCodePage = atol( buff );
322 return ( localeCodePage == codepage );
325 inline
326 sal_Bool SAL_CALL CFormatRegistrar::isLocaleOemCodePage( LCID lcid, sal_uInt32 codepage )
328 return isLocaleCodePage( lcid, LOCALE_IDEFAULTCODEPAGE, codepage );
331 inline
332 sal_Bool SAL_CALL CFormatRegistrar::isLocaleAnsiCodePage( LCID lcid, sal_uInt32 codepage )
334 return isLocaleCodePage( lcid, LOCALE_IDEFAULTANSICODEPAGE, codepage );
337 BOOL CALLBACK CFormatRegistrar::EnumLocalesProc( LPSTR lpLocaleStr )
339 // the lpLocaleStr parametere is hexadecimal
340 LCID lcid = strtol( lpLocaleStr, NULL, 16 );
342 if ( isLocaleAnsiCodePage( lcid, CFormatRegistrar::m_TxtCodePage ) ||
343 isLocaleOemCodePage( lcid, CFormatRegistrar::m_TxtCodePage ) )
345 CFormatRegistrar::m_TxtLocale = lcid;
346 return sal_False; // stop enumerating
349 return sal_True;
352 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */