LibreOffice Module dtrans (master)  1
FetcList.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 <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>
26 
27 #include "DataFmtTransl.hxx"
28 #include "../misc/ImplHelper.hxx"
29 #include <WinClip.hxx>
30 
31 #include <algorithm>
32 
33 #include "MimeAttrib.hxx"
34 
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;
40 
42 sal_uInt32 CFormatRegistrar::m_TxtCodePage = GetACP( );
43 
45 {
46  m_EnumIterator = m_FormatMap.begin( );
47 }
48 
50 {
51  m_FormatMap.push_back( fetc );
52 }
53 
55 {
56  FormatEtcMap_t::iterator iter =
57  find( m_FormatMap.begin(), m_FormatMap.end(), fetc );
58 
59  if ( iter != m_FormatMap.end( ) )
60  m_FormatMap.erase( iter );
61 }
62 
64 {
65  m_FormatMap.clear( );
66 }
67 
69 {
70  FormatEtcMap_t::const_iterator iter =
71  find( m_FormatMap.begin(), m_FormatMap.end(), fetc );
72 
73  return ( iter != m_FormatMap.end( ) );
74 }
75 
77 {
78  return !m_FormatMap.empty();
79 }
80 
82 {
83  m_EnumIterator = m_FormatMap.begin( );
84 }
85 
86 sal_uInt32 CFormatEtcContainer::nextFormatEtc( LPFORMATETC lpFetc,
87  sal_uInt32 aNum )
88 {
89  OSL_ASSERT( lpFetc );
90  OSL_ASSERT( !IsBadWritePtr( lpFetc, sizeof( FORMATETC ) * aNum ) );
91 
92  sal_uInt32 nFetched = 0;
93 
94  for ( sal_uInt32 i = 0; i < aNum; i++, nFetched++, lpFetc++, ++m_EnumIterator )
95  {
96  if ( m_EnumIterator == m_FormatMap.end() )
97  break;
98  CopyFormatEtc( lpFetc, *m_EnumIterator );
99  }
100 
101  return nFetched;
102 }
103 
104 bool CFormatEtcContainer::skipFormatEtc( sal_uInt32 aNum )
105 {
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 */
111 
112  return ( m_EnumIterator != m_FormatMap.end( ) );
113 }
114 
116  const CDataFormatTranslator& aDataFormatTranslator ) :
117  m_DataFormatTranslator( aDataFormatTranslator ),
118  m_bHasSynthesizedLocale( false ),
119  m_xContext( rxContext )
120 {
121 }
122 
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.:
126 //
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 // | |
139 //
140 // if some tries to register different text formats with different charsets the last
141 // registered wins and the others are ignored
142 
144  const Reference< XTransferable >& aXTransferable, CFormatEtcContainer& aFormatEtcContainer )
145 {
146  Sequence< DataFlavor > aFlavorList = aXTransferable->getTransferDataFlavors( );
147  sal_Int32 nFlavors = aFlavorList.getLength( );
148  bool bUnicodeRegistered = false;
149  DataFlavor aFlavor;
150 
151  for( sal_Int32 i = 0; i < nFlavors; i++ )
152  {
153  aFlavor = aFlavorList[i];
155 
156  // maybe an internal format so we ignore it
157  if ( CF_INVALID == fetc.getClipformat( ) )
158  continue;
159 
160  if ( !needsToSynthesizeAccompanyFormats( fetc ) )
161  aFormatEtcContainer.addFormatEtc( fetc );
162  else
163  {
164  // if we haven't registered any text format up to now
165  if ( CDataFormatTranslator::isTextFormat( fetc.getClipformat() ) && !bUnicodeRegistered )
166  {
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
172  {
173  aFormatEtcContainer.addFormatEtc( fetc ); // add CF_UNICODE
174  aFormatEtcContainer.addFormatEtc(
175  CDataFormatTranslator::getFormatEtcForClipformat( CF_TEXT ) ); // add CF_TEXT
176  bUnicodeRegistered = true;
177  }
178  else if ( !hasUnicodeFlavor( aXTransferable ) )
179  {
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 );
185 
186  // we try to get a Locale appropriate for this codepage
187  if ( findLocaleForTextCodePage( ) )
188  {
189  m_TxtCodePage = txtCP;
190 
191  aFormatEtcContainer.addFormatEtc(
193 
194  if ( !IsOEMCP( m_TxtCodePage ) )
195  aFormatEtcContainer.addFormatEtc(
197  else
198  aFormatEtcContainer.addFormatEtc(
200 
201  aFormatEtcContainer.addFormatEtc(
203 
204  // we save the flavor so it's easier when
205  // queried for it in XTDataObject::GetData(...)
206  m_RegisteredTextFlavor = aFlavor;
208  }
209  }
210  }
211  else if ( CDataFormatTranslator::isTextHtmlFormat( fetc.getClipformat( ) ) ) // Html (Hyper Text...)
212  {
213  // we add text/html ( HTML (HyperText Markup Language) )
214  aFormatEtcContainer.addFormatEtc( fetc );
215 
216  // and HTML Format
217  aFormatEtcContainer.addFormatEtc(
219  }
220  }
221  }
222 }
223 
225 {
227 }
228 
230 {
231  return m_TxtLocale;
232 }
233 
235 {
236  return m_TxtCodePage;
237 }
238 
240 {
241  return m_RegisteredTextFlavor;
242 }
243 
245 {
249 }
250 
251 inline
253 {
257 }
258 
259 OUString CFormatRegistrar::getCharsetFromDataFlavor( const DataFlavor& aFlavor )
260 {
261  OUString charset;
262 
263  try
264  {
266  MimeContentTypeFactory::create(m_xContext);
267 
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 );
273  }
274  catch(NoSuchElementException&)
275  {
276  OSL_FAIL( "Unexpected" );
277  }
278  catch(...)
279  {
280  OSL_FAIL( "Invalid data flavor" );
281  }
282 
283  return charset;
284 }
285 
287 {
288  CFormatEtc fetc( CF_UNICODETEXT );
289 
290  DataFlavor aFlavor =
292 
293  return aXTransferable->isDataFlavorSupported( aFlavor );
294 }
295 
297 {
298  m_TxtLocale = 0;
299  EnumSystemLocalesA( CFormatRegistrar::EnumLocalesProc, LCID_INSTALLED );
300  return IsValidLocale( m_TxtLocale, LCID_INSTALLED );
301 }
302 
303 bool CFormatRegistrar::isLocaleCodePage( LCID lcid, LCTYPE lctype, sal_uInt32 codepage )
304 {
305  char buff[6];
306  sal_uInt32 localeCodePage;
307 
308  OSL_ASSERT( IsValidLocale( lcid, LCID_INSTALLED ) );
309 
310  // get the ansi codepage of the current locale
311  GetLocaleInfoA( lcid, lctype, buff, sizeof( buff ) );
312  localeCodePage = atol( buff );
313 
314  return ( localeCodePage == codepage );
315 }
316 
317 inline
318 bool CFormatRegistrar::isLocaleOemCodePage( LCID lcid, sal_uInt32 codepage )
319 {
320  return isLocaleCodePage( lcid, LOCALE_IDEFAULTCODEPAGE, codepage );
321 }
322 
323 inline
324 bool CFormatRegistrar::isLocaleAnsiCodePage( LCID lcid, sal_uInt32 codepage )
325 {
326  return isLocaleCodePage( lcid, LOCALE_IDEFAULTANSICODEPAGE, codepage );
327 }
328 
330 {
331  // the lpLocaleStr parameter is hexadecimal
332  LCID lcid = strtol( lpLocaleStr, nullptr, 16 );
333 
336  {
338  return false; // stop enumerating
339  }
340 
341  return true;
342 }
343 
344 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool IsOEMCP(sal_uInt32 codepage)
Definition: ImplHelper.cxx:133
static bool isSynthesizeableFormat(const CFormatEtc &aFormatEtc)
Definition: FetcList.cxx:244
static bool isLocaleOemCodePage(LCID lcid, sal_uInt32 codepage)
Definition: FetcList.cxx:318
static bool isLocaleCodePage(LCID lcid, LCTYPE lctype, sal_uInt32 codepage)
Definition: FetcList.cxx:303
static bool isUnicodeTextFormat(CLIPFORMAT cf)
bool hasElements() const
Definition: FetcList.cxx:76
CFormatEtc getFormatEtcFromDataFlavor(const css::datatransfer::DataFlavor &aDataFlavor) const
CLIPFORMAT getClipformat() const
Definition: Fetc.cxx:97
void removeFormatEtc(const CFormatEtc &fetc)
Definition: FetcList.cxx:54
static bool needsToSynthesizeAccompanyFormats(const CFormatEtc &aFormatEtc)
Definition: FetcList.cxx:252
bool hasFormatEtc(const CFormatEtc &fetc) const
Definition: FetcList.cxx:68
static bool findLocaleForTextCodePage()
Definition: FetcList.cxx:296
const CDataFormatTranslator & m_DataFormatTranslator
Definition: FetcList.hxx:126
OUString getCharsetFromDataFlavor(const css::datatransfer::DataFlavor &aFlavor)
Definition: FetcList.cxx:259
OUString getMimeCharsetFromWinCP(sal_uInt32 cp, const OUString &aPrefix)
Definition: ImplHelper.cxx:116
const wchar_t *typedef BOOL
void removeAllFormatEtc()
Definition: FetcList.cxx:63
css::datatransfer::DataFlavor getDataFlavorFromFormatEtc(const FORMATETC &aFormatEtc, LCID lcid=GetThreadLocale()) const
bool m_bHasSynthesizedLocale
Definition: FetcList.hxx:127
bool CopyFormatEtc(LPFORMATETC petcDest, LPFORMATETC petcSrc)
Definition: ImplHelper.cxx:235
void beginEnumFormatEtc()
Definition: FetcList.cxx:81
static bool isHTMLFormat(CLIPFORMAT cf)
CFormatRegistrar(const css::uno::Reference< css::uno::XComponentContext > &rxContext, const CDataFormatTranslator &aDataFormatTranslator)
static CFormatEtc getFormatEtcForClipformat(CLIPFORMAT cf)
static bool isOemOrAnsiTextFormat(CLIPFORMAT cf)
const OUString PRE_WINDOWS_CODEPAGE("windows")
int i
OSQLColumns::const_iterator find(const OSQLColumns::const_iterator &first, const OSQLColumns::const_iterator &last, const OUString &_rVal, const ::comphelper::UStringMixEqual &_rCase)
static CFormatEtc getFormatEtcForClipformatName(const OUString &aClipFmtName)
static bool isTextFormat(CLIPFORMAT cf)
bool hasUnicodeFlavor(const css::uno::Reference< css::datatransfer::XTransferable > &aXTransferable) const
Definition: FetcList.cxx:286
void RegisterFormats(const css::uno::Reference< css::datatransfer::XTransferable > &aXTransferable, CFormatEtcContainer &aFormatEtcContainer)
Definition: FetcList.cxx:143
static bool isLocaleAnsiCodePage(LCID lcid, sal_uInt32 codepage)
Definition: FetcList.cxx:324
static LCID getSynthesizedLocale()
Definition: FetcList.cxx:229
bool hasSynthesizedLocale() const
Definition: FetcList.cxx:224
bool skipFormatEtc(sal_uInt32 aNum)
Definition: FetcList.cxx:104
sal_uInt32 nextFormatEtc(LPFORMATETC lpFetc, sal_uInt32 aNum=1)
Definition: FetcList.cxx:86
css::datatransfer::DataFlavor m_RegisteredTextFlavor
Definition: FetcList.hxx:128
css::datatransfer::DataFlavor getRegisteredTextFlavor() const
Definition: FetcList.cxx:239
static LCID m_TxtLocale
Definition: FetcList.hxx:132
static bool isTextHtmlFormat(CLIPFORMAT cf)
const css::uno::Reference< css::uno::XComponentContext > m_xContext
Definition: FetcList.hxx:130
static sal_uInt32 m_TxtCodePage
Definition: FetcList.hxx:133
const OUString TEXTPLAIN_PARAM_CHARSET("charset")
Reference< XComponentContext > m_xContext
#define CALLBACK
void addFormatEtc(const CFormatEtc &fetc)
Definition: FetcList.cxx:49
static sal_uInt32 getRegisteredTextCodePage()
Definition: FetcList.cxx:234
static BOOL CALLBACK EnumLocalesProc(LPSTR lpLocaleStr)
Definition: FetcList.cxx:329
sal_uInt32 getWinCPFromMimeCharset(const OUString &charset)
Definition: ImplHelper.cxx:41
const sal_Int32 CF_INVALID
Definition: WinClip.hxx:25