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 "../misc/WinClip.hxx"
26 #include "MimeAttrib.hxx"
27 #include "DTransHelper.hxx"
28 #include <rtl/string.h>
30 #include <com/sun/star/datatransfer/DataFormatTranslator.hpp>
33 #pragma warning(push,1)
34 #pragma warning(disable:4917)
42 // namespace directives
45 using namespace com::sun::star::uno
;
46 using namespace com::sun::star::datatransfer
;
47 using namespace com::sun::star::lang
;
49 const Type CPPUTYPE_SALINT32
= cppu::UnoType
<sal_Int32
>::get();
50 const Type CPPUTYPE_SALINT8
= cppu::UnoType
<sal_Int8
>::get();
51 const Type CPPUTYPE_OUSTRING
= cppu::UnoType
<OUString
>::get();
52 const Type CPPUTYPE_SEQSALINT8
= cppu::UnoType
<Sequence
< sal_Int8
>>::get();
53 const sal_Int32 MAX_CLIPFORMAT_NAME
= 256;
55 const OUString
TEXT_PLAIN_CHARSET ("text/plain;charset=");
56 const OUString
HPNAME_OEM_ANSI_TEXT ("OEM/ANSI Text");
58 const OUString
HTML_FORMAT_NAME_WINDOWS ("HTML Format");
59 const OUString
HTML_FORMAT_NAME_SOFFICE ("HTML (HyperText Markup Language)");
61 CDataFormatTranslator::CDataFormatTranslator( const Reference
< XComponentContext
>& rxContext
)
63 m_XDataFormatTranslator
= DataFormatTranslator::create( rxContext
);
66 CFormatEtc
CDataFormatTranslator::getFormatEtcFromDataFlavor( const DataFlavor
& aDataFlavor
) const
68 sal_Int32 cf
= CF_INVALID
;
72 if( m_XDataFormatTranslator
.is( ) )
74 Any aFormat
= m_XDataFormatTranslator
->getSystemDataTypeFromDataFlavor( aDataFlavor
);
76 if ( aFormat
.hasValue( ) )
78 if ( aFormat
.getValueType( ) == CPPUTYPE_SALINT32
)
81 OSL_ENSURE( CF_INVALID
!= cf
, "Invalid Clipboard format delivered" );
83 else if ( aFormat
.getValueType( ) == CPPUTYPE_OUSTRING
)
85 OUString aClipFmtName
;
86 aFormat
>>= aClipFmtName
;
88 OSL_ASSERT( aClipFmtName
.getLength( ) );
89 cf
= RegisterClipboardFormatW( reinterpret_cast<LPCWSTR
>(aClipFmtName
.getStr( )) );
91 OSL_ENSURE( CF_INVALID
!= cf
, "RegisterClipboardFormat failed" );
94 OSL_FAIL( "Wrong Any-Type detected" );
100 OSL_FAIL( "Unexpected error" );
103 return sal::static_int_cast
<CFormatEtc
>(getFormatEtcForClipformat( sal::static_int_cast
<CLIPFORMAT
>(cf
) ));
106 DataFlavor
CDataFormatTranslator::getDataFlavorFromFormatEtc( const FORMATETC
& aFormatEtc
, LCID lcid
) const
112 CLIPFORMAT aClipformat
= aFormatEtc
.cfFormat
;
115 aAny
<<= static_cast< sal_Int32
>( aClipformat
);
117 if ( isOemOrAnsiTextFormat( aClipformat
) )
119 aFlavor
.MimeType
= TEXT_PLAIN_CHARSET
;
120 aFlavor
.MimeType
+= getTextCharsetFromLCID( lcid
, aClipformat
);
122 aFlavor
.HumanPresentableName
= HPNAME_OEM_ANSI_TEXT
;
123 aFlavor
.DataType
= CPPUTYPE_SEQSALINT8
;
125 else if ( CF_INVALID
!= aClipformat
)
127 if ( m_XDataFormatTranslator
.is( ) )
129 aFlavor
= m_XDataFormatTranslator
->getDataFlavorFromSystemDataType( aAny
);
131 if ( !aFlavor
.MimeType
.getLength( ) )
133 // lookup of DataFlavor from clipboard format id
134 // failed, so we try to resolve via clipboard
136 OUString clipFormatName
= getClipboardFormatName( aClipformat
);
138 // if we could not get a clipboard format name an
139 // error must have occurred or it is a standard
140 // clipboard format that we don't translate, e.g.
141 // CF_BITMAP (the office only uses CF_DIB)
142 if ( clipFormatName
.getLength( ) )
144 aAny
<<= clipFormatName
;
145 aFlavor
= m_XDataFormatTranslator
->getDataFlavorFromSystemDataType( aAny
);
153 OSL_FAIL( "Unexpected error" );
159 CFormatEtc SAL_CALL
CDataFormatTranslator::getFormatEtcForClipformatName( const OUString
& aClipFmtName
) const
162 if ( !aClipFmtName
.getLength( ) )
163 return CFormatEtc( CF_INVALID
);
165 CLIPFORMAT cf
= sal::static_int_cast
<CLIPFORMAT
>(RegisterClipboardFormatW( reinterpret_cast<LPCWSTR
>(aClipFmtName
.getStr( )) ));
166 return getFormatEtcForClipformat( cf
);
169 OUString
CDataFormatTranslator::getClipboardFormatName( CLIPFORMAT aClipformat
) const
171 OSL_PRECOND( CF_INVALID
!= aClipformat
, "Invalid clipboard format" );
173 sal_Unicode wBuff
[ MAX_CLIPFORMAT_NAME
+ 1 ]; // Null terminator isn't counted, apparently.
174 sal_Int32 nLen
= GetClipboardFormatNameW( aClipformat
, reinterpret_cast<LPWSTR
>(wBuff
), MAX_CLIPFORMAT_NAME
);
176 return OUString( wBuff
, nLen
);
179 CFormatEtc SAL_CALL
CDataFormatTranslator::getFormatEtcForClipformat( CLIPFORMAT cf
) const
181 CFormatEtc
fetc( cf
, TYMED_NULL
, NULL
, DVASPECT_CONTENT
);
185 case CF_METAFILEPICT
:
186 fetc
.setTymed( TYMED_MFPICT
);
190 fetc
.setTymed( TYMED_ENHMF
);
194 fetc
.setTymed( TYMED_HGLOBAL
/*| TYMED_ISTREAM*/ );
198 hack: in order to paste urls copied by Internet Explorer
199 with "copy link" we set the lindex member to 0
200 but if we really want to support CFSTR_FILECONTENT and
201 the accompany format CFSTR_FILEDESCRIPTOR (FileGroupDescriptor)
202 the client of the clipboard service has to provide a id
203 of which FileContents it wants to paste
204 see MSDN: "Handling Shell Data Transfer Scenarios"
206 if ( cf
== RegisterClipboardFormatA( CFSTR_FILECONTENTS
) )
212 sal_Bool SAL_CALL
CDataFormatTranslator::isOemOrAnsiTextFormat( CLIPFORMAT cf
) const
214 return ( (cf
== CF_TEXT
) || (cf
== CF_OEMTEXT
) );
217 sal_Bool SAL_CALL
CDataFormatTranslator::isUnicodeTextFormat( CLIPFORMAT cf
) const
219 return ( cf
== CF_UNICODETEXT
);
222 sal_Bool SAL_CALL
CDataFormatTranslator::isTextFormat( CLIPFORMAT cf
) const
224 return ( isOemOrAnsiTextFormat( cf
) || isUnicodeTextFormat( cf
) );
227 sal_Bool SAL_CALL
CDataFormatTranslator::isHTMLFormat( CLIPFORMAT cf
) const
229 OUString clipFormatName
= getClipboardFormatName( cf
);
230 return ( clipFormatName
== HTML_FORMAT_NAME_WINDOWS
);
233 sal_Bool SAL_CALL
CDataFormatTranslator::isTextHtmlFormat( CLIPFORMAT cf
) const
235 OUString clipFormatName
= getClipboardFormatName( cf
);
236 return ( clipFormatName
.equalsIgnoreAsciiCase( HTML_FORMAT_NAME_SOFFICE
) );
239 OUString SAL_CALL
CDataFormatTranslator::getTextCharsetFromLCID( LCID lcid
, CLIPFORMAT aClipformat
) const
241 OSL_ASSERT( isOemOrAnsiTextFormat( aClipformat
) );
244 if ( CF_TEXT
== aClipformat
)
246 charset
= getMimeCharsetFromLocaleId(
248 LOCALE_IDEFAULTANSICODEPAGE
,
249 PRE_WINDOWS_CODEPAGE
);
251 else if ( CF_OEMTEXT
== aClipformat
)
253 charset
= getMimeCharsetFromLocaleId(
255 LOCALE_IDEFAULTCODEPAGE
,
259 OSL_ASSERT( sal_False
);
264 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */