Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / dtrans / source / win32 / dtobj / FetcList.cxx
blob0a262b0677fb7c2da930dd147178a01442eb6d13
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/container/NoSuchElementException.hpp>
24 #include <com/sun/star/datatransfer/MimeContentTypeFactory.hpp>
25 #include <com/sun/star/datatransfer/XMimeContentType.hpp>
27 #include "DataFmtTransl.hxx"
28 #include "../misc/ImplHelper.hxx"
29 #include <WinClip.hxx>
31 #include <algorithm>
33 #include "MimeAttrib.hxx"
35 using namespace com::sun::star::uno;
36 using namespace com::sun::star::datatransfer;
37 using namespace com::sun::star::lang;
38 using namespace com::sun::star::container;
39 using namespace std;
41 LCID CFormatRegistrar::m_TxtLocale = 0;
42 sal_uInt32 CFormatRegistrar::m_TxtCodePage = GetACP( );
44 CFormatEtcContainer::CFormatEtcContainer( )
46 m_EnumIterator = m_FormatMap.begin( );
49 void CFormatEtcContainer::addFormatEtc( const CFormatEtc& fetc )
51 m_FormatMap.push_back( fetc );
54 void CFormatEtcContainer::removeFormatEtc( const CFormatEtc& fetc )
56 FormatEtcMap_t::iterator iter =
57 find( m_FormatMap.begin(), m_FormatMap.end(), fetc );
59 if ( iter != m_FormatMap.end( ) )
60 m_FormatMap.erase( iter );
63 void CFormatEtcContainer::removeAllFormatEtc( )
65 m_FormatMap.clear( );
68 bool CFormatEtcContainer::hasFormatEtc( const CFormatEtc& fetc ) const
70 FormatEtcMap_t::const_iterator iter =
71 find( m_FormatMap.begin(), m_FormatMap.end(), fetc );
73 return ( iter != m_FormatMap.end( ) );
76 bool CFormatEtcContainer::hasElements( ) const
78 return !m_FormatMap.empty();
81 void CFormatEtcContainer::beginEnumFormatEtc( )
83 m_EnumIterator = m_FormatMap.begin( );
86 sal_uInt32 CFormatEtcContainer::nextFormatEtc( LPFORMATETC lpFetc,
87 sal_uInt32 aNum )
89 OSL_ASSERT( lpFetc );
90 OSL_ASSERT( !IsBadWritePtr( lpFetc, sizeof( FORMATETC ) * aNum ) );
92 sal_uInt32 nFetched = 0;
94 for ( sal_uInt32 i = 0; i < aNum; i++, nFetched++, lpFetc++, ++m_EnumIterator )
96 if ( m_EnumIterator == m_FormatMap.end() )
97 break;
98 CopyFormatEtc( lpFetc, *m_EnumIterator );
101 return nFetched;
104 bool CFormatEtcContainer::skipFormatEtc( sal_uInt32 aNum )
106 FormatEtcMap_t::const_iterator iter_end = m_FormatMap.end( );
107 for ( sal_uInt32 i = 0;
108 (i < aNum) && (m_EnumIterator != iter_end);
109 i++, ++m_EnumIterator )
110 ;/* intentionally left empty */
112 return ( m_EnumIterator != m_FormatMap.end( ) );
115 CFormatRegistrar::CFormatRegistrar( const Reference< XComponentContext >& rxContext,
116 const CDataFormatTranslator& aDataFormatTranslator ) :
117 m_DataFormatTranslator( aDataFormatTranslator ),
118 m_bHasSynthesizedLocale( false ),
119 m_xContext( rxContext )
123 // this function converts all DataFlavors of the given FlavorList into
124 // an appropriate FORMATETC structure, for some formats like unicodetext,
125 // text and text/html we will offer an accompany format e.g.:
127 // DataFlavor | Registered Clipformat | Registered accompany clipformat
128 // -------------------------|---------------------------|-----------------------------------
129 // text/plain;charset=ansi | CF_TEXT | CF_UNICODETEXT
130 // | | CF_LOCALE (if charset != GetACP()
131 // | |
132 // text/plain;charset=oem | CF_OEMTEXT | CF_UNICODETEXT
133 // | | CF_LOCALE (if charset != GetOEMCP()
134 // | |
135 // text/plain;charset=utf-16| CF_UNICODETEXT | CF_TEXT
136 // | |
137 // text/html | HTML (Hypertext ...) | HTML Format
138 // | |
140 // if some tries to register different text formats with different charsets the last
141 // registered wins and the others are ignored
143 void CFormatRegistrar::RegisterFormats(
144 const Reference< XTransferable >& aXTransferable, CFormatEtcContainer& aFormatEtcContainer )
146 Sequence< DataFlavor > aFlavorList = aXTransferable->getTransferDataFlavors( );
147 sal_Int32 nFlavors = aFlavorList.getLength( );
148 bool bUnicodeRegistered = false;
149 DataFlavor aFlavor;
151 for( sal_Int32 i = 0; i < nFlavors; i++ )
153 aFlavor = aFlavorList[i];
154 CFormatEtc fetc = m_DataFormatTranslator.getFormatEtcFromDataFlavor( aFlavor );
156 // maybe an internal format so we ignore it
157 if ( CF_INVALID == fetc.getClipformat( ) )
158 continue;
160 if ( !needsToSynthesizeAccompanyFormats( fetc ) )
161 aFormatEtcContainer.addFormatEtc( fetc );
162 else
164 // if we haven't registered any text format up to now
165 if ( CDataFormatTranslator::isTextFormat( fetc.getClipformat() ) && !bUnicodeRegistered )
167 // if the transferable supports unicode text we ignore
168 // any further text format the transferable offers
169 // because we can create it from Unicode text in addition
170 // we register CF_TEXT for non unicode clients
171 if ( CDataFormatTranslator::isUnicodeTextFormat( fetc.getClipformat() ) )
173 aFormatEtcContainer.addFormatEtc( fetc ); // add CF_UNICODE
174 aFormatEtcContainer.addFormatEtc(
175 CDataFormatTranslator::getFormatEtcForClipformat( CF_TEXT ) ); // add CF_TEXT
176 bUnicodeRegistered = true;
178 else if ( !hasUnicodeFlavor( aXTransferable ) )
180 // we try to investigate the charset and make a valid
181 // windows codepage from this charset the default
182 // return value is the result of GetACP( )
183 OUString charset = getCharsetFromDataFlavor( aFlavor );
184 sal_uInt32 txtCP = getWinCPFromMimeCharset( charset );
186 // we try to get a Locale appropriate for this codepage
187 if ( findLocaleForTextCodePage( ) )
189 m_TxtCodePage = txtCP;
191 aFormatEtcContainer.addFormatEtc(
192 CDataFormatTranslator::getFormatEtcForClipformat( CF_UNICODETEXT ) );
194 if ( !IsOEMCP( m_TxtCodePage ) )
195 aFormatEtcContainer.addFormatEtc(
196 CDataFormatTranslator::getFormatEtcForClipformat( CF_TEXT ) );
197 else
198 aFormatEtcContainer.addFormatEtc(
199 CDataFormatTranslator::getFormatEtcForClipformat( CF_OEMTEXT ) );
201 aFormatEtcContainer.addFormatEtc(
202 CDataFormatTranslator::getFormatEtcForClipformat( CF_LOCALE ) );
204 // we save the flavor so it's easier when
205 // queried for it in XTDataObject::GetData(...)
206 m_RegisteredTextFlavor = aFlavor;
207 m_bHasSynthesizedLocale = true;
211 else if ( CDataFormatTranslator::isTextHtmlFormat( fetc.getClipformat( ) ) ) // Html (Hyper Text...)
213 // we add text/html ( HTML (HyperText Markup Language) )
214 aFormatEtcContainer.addFormatEtc( fetc );
216 // and HTML Format
217 aFormatEtcContainer.addFormatEtc(
218 CDataFormatTranslator::getFormatEtcForClipformatName( "HTML Format" ) );
224 bool CFormatRegistrar::hasSynthesizedLocale( ) const
226 return m_bHasSynthesizedLocale;
229 LCID CFormatRegistrar::getSynthesizedLocale( )
231 return m_TxtLocale;
234 sal_uInt32 CFormatRegistrar::getRegisteredTextCodePage( )
236 return m_TxtCodePage;
239 DataFlavor CFormatRegistrar::getRegisteredTextFlavor( ) const
241 return m_RegisteredTextFlavor;
244 bool CFormatRegistrar::isSynthesizeableFormat( const CFormatEtc& aFormatEtc )
246 return ( CDataFormatTranslator::isOemOrAnsiTextFormat( aFormatEtc.getClipformat() ) ||
247 CDataFormatTranslator::isUnicodeTextFormat( aFormatEtc.getClipformat() ) ||
248 CDataFormatTranslator::isHTMLFormat( aFormatEtc.getClipformat() ) );
251 inline
252 bool CFormatRegistrar::needsToSynthesizeAccompanyFormats( const CFormatEtc& aFormatEtc )
254 return ( CDataFormatTranslator::isOemOrAnsiTextFormat( aFormatEtc.getClipformat() ) ||
255 CDataFormatTranslator::isUnicodeTextFormat( aFormatEtc.getClipformat() ) ||
256 CDataFormatTranslator::isTextHtmlFormat( aFormatEtc.getClipformat( ) ) );
259 OUString CFormatRegistrar::getCharsetFromDataFlavor( const DataFlavor& aFlavor )
261 OUString charset;
265 Reference< XMimeContentTypeFactory > xMimeFac =
266 MimeContentTypeFactory::create(m_xContext);
268 Reference< XMimeContentType > xMimeType( xMimeFac->createMimeContentType( aFlavor.MimeType ) );
269 if ( xMimeType->hasParameter( TEXTPLAIN_PARAM_CHARSET ) )
270 charset = xMimeType->getParameterValue( TEXTPLAIN_PARAM_CHARSET );
271 else
272 charset = getMimeCharsetFromWinCP( GetACP( ), PRE_WINDOWS_CODEPAGE );
274 catch(NoSuchElementException&)
276 OSL_FAIL( "Unexpected" );
278 catch(...)
280 OSL_FAIL( "Invalid data flavor" );
283 return charset;
286 bool CFormatRegistrar::hasUnicodeFlavor( const Reference< XTransferable >& aXTransferable ) const
288 CFormatEtc fetc( CF_UNICODETEXT );
290 DataFlavor aFlavor =
291 m_DataFormatTranslator.getDataFlavorFromFormatEtc( fetc );
293 return aXTransferable->isDataFlavorSupported( aFlavor );
296 bool CFormatRegistrar::findLocaleForTextCodePage( )
298 m_TxtLocale = 0;
299 EnumSystemLocalesA( CFormatRegistrar::EnumLocalesProc, LCID_INSTALLED );
300 return IsValidLocale( m_TxtLocale, LCID_INSTALLED );
303 bool CFormatRegistrar::isLocaleCodePage( LCID lcid, LCTYPE lctype, sal_uInt32 codepage )
305 char buff[6];
306 sal_uInt32 localeCodePage;
308 OSL_ASSERT( IsValidLocale( lcid, LCID_INSTALLED ) );
310 // get the ansi codepage of the current locale
311 GetLocaleInfoA( lcid, lctype, buff, sizeof( buff ) );
312 localeCodePage = atol( buff );
314 return ( localeCodePage == codepage );
317 inline
318 bool CFormatRegistrar::isLocaleOemCodePage( LCID lcid, sal_uInt32 codepage )
320 return isLocaleCodePage( lcid, LOCALE_IDEFAULTCODEPAGE, codepage );
323 inline
324 bool CFormatRegistrar::isLocaleAnsiCodePage( LCID lcid, sal_uInt32 codepage )
326 return isLocaleCodePage( lcid, LOCALE_IDEFAULTANSICODEPAGE, codepage );
329 BOOL CALLBACK CFormatRegistrar::EnumLocalesProc( LPSTR lpLocaleStr )
331 // the lpLocaleStr parameter is hexadecimal
332 LCID lcid = strtol( lpLocaleStr, nullptr, 16 );
334 if ( isLocaleAnsiCodePage( lcid, CFormatRegistrar::m_TxtCodePage ) ||
335 isLocaleOemCodePage( lcid, CFormatRegistrar::m_TxtCodePage ) )
337 CFormatRegistrar::m_TxtLocale = lcid;
338 return false; // stop enumerating
341 return true;
344 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */