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 "../misc/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
40 using namespace com::sun::star::uno
;
41 using namespace com::sun::star::datatransfer
;
42 using namespace com::sun::star::lang
;
44 const Type CPPUTYPE_SALINT32
= cppu::UnoType
<sal_Int32
>::get();
45 const Type CPPUTYPE_SALINT8
= cppu::UnoType
<sal_Int8
>::get();
46 const Type CPPUTYPE_OUSTRING
= cppu::UnoType
<OUString
>::get();
47 const Type CPPUTYPE_SEQSALINT8
= cppu::UnoType
<Sequence
< sal_Int8
>>::get();
48 const sal_Int32 MAX_CLIPFORMAT_NAME
= 256;
50 const OUString
TEXT_PLAIN_CHARSET ("text/plain;charset=");
51 const OUString
HPNAME_OEM_ANSI_TEXT ("OEM/ANSI Text");
53 const OUString
HTML_FORMAT_NAME_WINDOWS ("HTML Format");
54 const OUString
HTML_FORMAT_NAME_SOFFICE ("HTML (HyperText Markup Language)");
56 CDataFormatTranslator::CDataFormatTranslator( const Reference
< XComponentContext
>& rxContext
)
58 m_XDataFormatTranslator
= DataFormatTranslator::create( rxContext
);
61 CFormatEtc
CDataFormatTranslator::getFormatEtcFromDataFlavor( const DataFlavor
& aDataFlavor
) const
63 sal_Int32 cf
= CF_INVALID
;
67 if( m_XDataFormatTranslator
.is( ) )
69 Any aFormat
= m_XDataFormatTranslator
->getSystemDataTypeFromDataFlavor( aDataFlavor
);
71 if ( aFormat
.hasValue( ) )
73 if ( aFormat
.getValueType( ) == CPPUTYPE_SALINT32
)
76 OSL_ENSURE( CF_INVALID
!= cf
, "Invalid Clipboard format delivered" );
78 else if ( aFormat
.getValueType( ) == CPPUTYPE_OUSTRING
)
80 OUString aClipFmtName
;
81 aFormat
>>= aClipFmtName
;
83 OSL_ASSERT( aClipFmtName
.getLength( ) );
84 cf
= RegisterClipboardFormatW( o3tl::toW(aClipFmtName
.getStr( )) );
86 OSL_ENSURE( CF_INVALID
!= cf
, "RegisterClipboardFormat failed" );
89 OSL_FAIL( "Wrong Any-Type detected" );
95 OSL_FAIL( "Unexpected error" );
98 return sal::static_int_cast
<CFormatEtc
>(getFormatEtcForClipformat( sal::static_int_cast
<CLIPFORMAT
>(cf
) ));
101 DataFlavor
CDataFormatTranslator::getDataFlavorFromFormatEtc( const FORMATETC
& aFormatEtc
, LCID lcid
) const
107 CLIPFORMAT aClipformat
= aFormatEtc
.cfFormat
;
110 aAny
<<= static_cast< sal_Int32
>( aClipformat
);
112 if ( isOemOrAnsiTextFormat( aClipformat
) )
114 aFlavor
.MimeType
= TEXT_PLAIN_CHARSET
;
115 aFlavor
.MimeType
+= getTextCharsetFromLCID( lcid
, aClipformat
);
117 aFlavor
.HumanPresentableName
= HPNAME_OEM_ANSI_TEXT
;
118 aFlavor
.DataType
= CPPUTYPE_SEQSALINT8
;
120 else if ( CF_INVALID
!= aClipformat
)
122 if ( m_XDataFormatTranslator
.is( ) )
124 aFlavor
= m_XDataFormatTranslator
->getDataFlavorFromSystemDataType( aAny
);
126 if ( !aFlavor
.MimeType
.getLength( ) )
128 // lookup of DataFlavor from clipboard format id
129 // failed, so we try to resolve via clipboard
131 OUString clipFormatName
= getClipboardFormatName( aClipformat
);
133 // if we could not get a clipboard format name an
134 // error must have occurred or it is a standard
135 // clipboard format that we don't translate, e.g.
136 // CF_BITMAP (the office only uses CF_DIB)
137 if ( clipFormatName
.getLength( ) )
139 aAny
<<= clipFormatName
;
140 aFlavor
= m_XDataFormatTranslator
->getDataFlavorFromSystemDataType( aAny
);
148 OSL_FAIL( "Unexpected error" );
154 CFormatEtc
CDataFormatTranslator::getFormatEtcForClipformatName( const OUString
& aClipFmtName
)
157 if ( !aClipFmtName
.getLength( ) )
158 return CFormatEtc( CF_INVALID
);
160 CLIPFORMAT cf
= sal::static_int_cast
<CLIPFORMAT
>(RegisterClipboardFormatW( o3tl::toW(aClipFmtName
.getStr( )) ));
161 return getFormatEtcForClipformat( cf
);
164 OUString
CDataFormatTranslator::getClipboardFormatName( CLIPFORMAT aClipformat
)
166 OSL_PRECOND( CF_INVALID
!= aClipformat
, "Invalid clipboard format" );
168 sal_Unicode wBuff
[ MAX_CLIPFORMAT_NAME
+ 1 ]; // Null terminator isn't counted, apparently.
169 sal_Int32 nLen
= GetClipboardFormatNameW( aClipformat
, o3tl::toW(wBuff
), MAX_CLIPFORMAT_NAME
);
171 return OUString( wBuff
, nLen
);
174 CFormatEtc
CDataFormatTranslator::getFormatEtcForClipformat( CLIPFORMAT cf
)
176 CFormatEtc
fetc( cf
, TYMED_NULL
, nullptr, DVASPECT_CONTENT
);
180 case CF_METAFILEPICT
:
181 fetc
.setTymed( TYMED_MFPICT
);
185 fetc
.setTymed( TYMED_ENHMF
);
189 fetc
.setTymed( TYMED_HGLOBAL
/*| TYMED_ISTREAM*/ );
193 hack: in order to paste urls copied by Internet Explorer
194 with "copy link" we set the lindex member to 0
195 but if we really want to support CFSTR_FILECONTENT and
196 the accompany format CFSTR_FILEDESCRIPTOR (FileGroupDescriptor)
197 the client of the clipboard service has to provide a id
198 of which FileContents it wants to paste
199 see MSDN: "Handling Shell Data Transfer Scenarios"
201 if ( cf
== RegisterClipboardFormat( CFSTR_FILECONTENTS
) )
207 bool CDataFormatTranslator::isOemOrAnsiTextFormat( CLIPFORMAT cf
)
209 return ( (cf
== CF_TEXT
) || (cf
== CF_OEMTEXT
) );
212 bool CDataFormatTranslator::isUnicodeTextFormat( CLIPFORMAT cf
)
214 return ( cf
== CF_UNICODETEXT
);
217 bool CDataFormatTranslator::isTextFormat( CLIPFORMAT cf
)
219 return ( isOemOrAnsiTextFormat( cf
) || isUnicodeTextFormat( cf
) );
222 bool CDataFormatTranslator::isHTMLFormat( CLIPFORMAT cf
)
224 OUString clipFormatName
= getClipboardFormatName( cf
);
225 return ( clipFormatName
== HTML_FORMAT_NAME_WINDOWS
);
228 bool CDataFormatTranslator::isTextHtmlFormat( CLIPFORMAT cf
)
230 OUString clipFormatName
= getClipboardFormatName( cf
);
231 return clipFormatName
.equalsIgnoreAsciiCase( HTML_FORMAT_NAME_SOFFICE
);
234 OUString
CDataFormatTranslator::getTextCharsetFromLCID( LCID lcid
, CLIPFORMAT aClipformat
)
236 OSL_ASSERT( isOemOrAnsiTextFormat( aClipformat
) );
239 if ( CF_TEXT
== aClipformat
)
241 charset
= getMimeCharsetFromLocaleId(
243 LOCALE_IDEFAULTANSICODEPAGE
,
244 PRE_WINDOWS_CODEPAGE
);
246 else if ( CF_OEMTEXT
== aClipformat
)
248 charset
= getMimeCharsetFromLocaleId(
250 LOCALE_IDEFAULTCODEPAGE
,
259 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */