1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 "DataFmtTransl.hxx"
21 #include <rtl/string.hxx>
22 #include <osl/diagnose.h>
23 #include <rtl/tencinfo.h>
24 #include "ImplHelper.hxx"
25 #include "WinClip.hxx"
26 #include "MimeAttrib.hxx"
27 #include "DTransHelper.hxx"
28 #include <rtl/string.h>
29 #include <o3tl/char16_t2wchar_t.hxx>
31 #include <com/sun/star/datatransfer/DataFormatTranslator.hpp>
33 #if !defined WIN32_LEAN_AND_MEAN
34 # define WIN32_LEAN_AND_MEAN
39 using namespace com::sun::star::uno
;
40 using namespace com::sun::star::datatransfer
;
41 using namespace com::sun::star::lang
;
43 const Type CPPUTYPE_SALINT32
= cppu::UnoType
<sal_Int32
>::get();
44 const Type CPPUTYPE_SALINT8
= cppu::UnoType
<sal_Int8
>::get();
45 const Type CPPUTYPE_OUSTRING
= cppu::UnoType
<OUString
>::get();
46 const Type CPPUTYPE_SEQSALINT8
= cppu::UnoType
<Sequence
< sal_Int8
>>::get();
47 const sal_Int32 MAX_CLIPFORMAT_NAME
= 256;
49 CDataFormatTranslator::CDataFormatTranslator( const Reference
< XComponentContext
>& rxContext
)
51 m_XDataFormatTranslator
= DataFormatTranslator::create( rxContext
);
54 CFormatEtc
CDataFormatTranslator::getFormatEtcFromDataFlavor( const DataFlavor
& aDataFlavor
) const
56 sal_Int32 cf
= CF_INVALID
;
60 if( m_XDataFormatTranslator
.is( ) )
62 Any aFormat
= m_XDataFormatTranslator
->getSystemDataTypeFromDataFlavor( aDataFlavor
);
64 if ( aFormat
.hasValue( ) )
66 if ( aFormat
.getValueType( ) == CPPUTYPE_SALINT32
)
69 OSL_ENSURE( CF_INVALID
!= cf
, "Invalid Clipboard format delivered" );
71 else if ( aFormat
.getValueType( ) == CPPUTYPE_OUSTRING
)
73 OUString aClipFmtName
;
74 aFormat
>>= aClipFmtName
;
76 OSL_ASSERT( aClipFmtName
.getLength( ) );
77 cf
= RegisterClipboardFormatW( o3tl::toW(aClipFmtName
.getStr( )) );
79 OSL_ENSURE( CF_INVALID
!= cf
, "RegisterClipboardFormat failed" );
82 OSL_FAIL( "Wrong Any-Type detected" );
88 OSL_FAIL( "Unexpected error" );
91 return sal::static_int_cast
<CFormatEtc
>(getFormatEtcForClipformat( sal::static_int_cast
<CLIPFORMAT
>(cf
) ));
94 DataFlavor
CDataFormatTranslator::getDataFlavorFromFormatEtc(sal_uInt32 cfFormat
, LCID lcid
) const
100 CLIPFORMAT aClipformat
= cfFormat
;
103 aAny
<<= static_cast< sal_Int32
>( aClipformat
);
105 if ( isOemOrAnsiTextFormat( aClipformat
) )
107 aFlavor
.MimeType
= "text/plain;charset=";
108 aFlavor
.MimeType
+= getTextCharsetFromLCID( lcid
, aClipformat
);
110 aFlavor
.HumanPresentableName
= "OEM/ANSI Text";
111 aFlavor
.DataType
= CPPUTYPE_SEQSALINT8
;
113 else if ( CF_INVALID
!= aClipformat
)
115 if ( m_XDataFormatTranslator
.is( ) )
117 aFlavor
= m_XDataFormatTranslator
->getDataFlavorFromSystemDataType( aAny
);
119 if ( !aFlavor
.MimeType
.getLength( ) )
121 // lookup of DataFlavor from clipboard format id
122 // failed, so we try to resolve via clipboard
124 OUString clipFormatName
= getClipboardFormatName( aClipformat
);
126 // if we could not get a clipboard format name an
127 // error must have occurred or it is a standard
128 // clipboard format that we don't translate, e.g.
129 // CF_BITMAP (the office only uses CF_DIB)
130 if ( clipFormatName
.getLength( ) )
132 aAny
<<= clipFormatName
;
133 aFlavor
= m_XDataFormatTranslator
->getDataFlavorFromSystemDataType( aAny
);
141 OSL_FAIL( "Unexpected error" );
147 CFormatEtc
CDataFormatTranslator::getFormatEtcForClipformatName( const OUString
& aClipFmtName
)
150 if ( !aClipFmtName
.getLength( ) )
151 return CFormatEtc( CF_INVALID
);
153 CLIPFORMAT cf
= sal::static_int_cast
<CLIPFORMAT
>(RegisterClipboardFormatW( o3tl::toW(aClipFmtName
.getStr( )) ));
154 return getFormatEtcForClipformat( cf
);
157 OUString
CDataFormatTranslator::getClipboardFormatName( CLIPFORMAT aClipformat
)
159 OSL_PRECOND( CF_INVALID
!= aClipformat
, "Invalid clipboard format" );
161 sal_Unicode wBuff
[ MAX_CLIPFORMAT_NAME
+ 1 ]; // Null terminator isn't counted, apparently.
162 sal_Int32 nLen
= GetClipboardFormatNameW( aClipformat
, o3tl::toW(wBuff
), MAX_CLIPFORMAT_NAME
);
164 return OUString( wBuff
, nLen
);
167 CFormatEtc
CDataFormatTranslator::getFormatEtcForClipformat( CLIPFORMAT cf
)
169 CFormatEtc
fetc( cf
, TYMED_NULL
, nullptr, DVASPECT_CONTENT
);
173 case CF_METAFILEPICT
:
174 fetc
.setTymed( TYMED_MFPICT
);
178 fetc
.setTymed( TYMED_ENHMF
);
182 fetc
.setTymed( TYMED_HGLOBAL
/*| TYMED_ISTREAM*/ );
186 hack: in order to paste urls copied by Internet Explorer
187 with "copy link" we set the lindex member to 0
188 but if we really want to support CFSTR_FILECONTENT and
189 the accompany format CFSTR_FILEDESCRIPTOR (FileGroupDescriptor)
190 the client of the clipboard service has to provide a id
191 of which FileContents it wants to paste
192 see MSDN: "Handling Shell Data Transfer Scenarios"
194 if ( cf
== RegisterClipboardFormat( CFSTR_FILECONTENTS
) )
200 bool CDataFormatTranslator::isOemOrAnsiTextFormat( CLIPFORMAT cf
)
202 return ( (cf
== CF_TEXT
) || (cf
== CF_OEMTEXT
) );
205 bool CDataFormatTranslator::isUnicodeTextFormat( CLIPFORMAT cf
)
207 return ( cf
== CF_UNICODETEXT
);
210 bool CDataFormatTranslator::isTextFormat( CLIPFORMAT cf
)
212 return ( isOemOrAnsiTextFormat( cf
) || isUnicodeTextFormat( cf
) );
215 bool CDataFormatTranslator::isHTMLFormat( CLIPFORMAT cf
)
217 OUString clipFormatName
= getClipboardFormatName( cf
);
218 return ( clipFormatName
== "HTML Format" );
221 bool CDataFormatTranslator::isTextHtmlFormat( CLIPFORMAT cf
)
223 OUString clipFormatName
= getClipboardFormatName( cf
);
224 return clipFormatName
.equalsIgnoreAsciiCase( "HTML (HyperText Markup Language)" );
227 OUString
CDataFormatTranslator::getTextCharsetFromLCID( LCID lcid
, CLIPFORMAT aClipformat
)
229 OSL_ASSERT( isOemOrAnsiTextFormat( aClipformat
) );
232 if ( CF_TEXT
== aClipformat
)
234 charset
= getMimeCharsetFromLocaleId(
236 LOCALE_IDEFAULTANSICODEPAGE
,
237 PRE_WINDOWS_CODEPAGE
);
239 else if ( CF_OEMTEXT
== aClipformat
)
241 charset
= getMimeCharsetFromLocaleId(
243 LOCALE_IDEFAULTCODEPAGE
,
252 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */