1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_dtrans.hxx" 30 31 //------------------------------------------------------------------------ 32 // includes 33 //------------------------------------------------------------------------ 34 #include "DataFmtTransl.hxx" 35 #include <rtl/string.hxx> 36 #include <osl/diagnose.h> 37 #include <rtl/tencinfo.h> 38 #include "..\misc\ImplHelper.hxx" 39 #include "..\misc\WinClip.hxx" 40 #include "MimeAttrib.hxx" 41 #include "DTransHelper.hxx" 42 #include <rtl/string.h> 43 #include "Fetc.hxx" 44 45 #if defined _MSC_VER 46 #pragma warning(push,1) 47 #pragma warning(disable:4917) 48 #endif 49 #include <windows.h> 50 #if (_MSC_VER < 1300) && !defined(__MINGW32__) 51 #include <olestd.h> 52 #endif 53 #include <shlobj.h> 54 #if defined _MSC_VER 55 #pragma warning(pop) 56 #endif 57 58 59 //------------------------------------------------------------------------ 60 // namespace directives 61 //------------------------------------------------------------------------ 62 63 using namespace rtl; 64 using namespace std; 65 using namespace com::sun::star::uno; 66 using namespace com::sun::star::datatransfer; 67 using namespace com::sun::star::lang; 68 69 //------------------------------------------------------------------------ 70 // const 71 //------------------------------------------------------------------------ 72 73 const Type CPPUTYPE_SALINT32 = getCppuType((sal_Int32*)0); 74 const Type CPPUTYPE_SALINT8 = getCppuType((sal_Int8*)0); 75 const Type CPPUTYPE_OUSTRING = getCppuType((OUString*)0); 76 const Type CPPUTYPE_SEQSALINT8 = getCppuType((Sequence< sal_Int8>*)0); 77 const sal_Int32 MAX_CLIPFORMAT_NAME = 256; 78 79 const OUString TEXT_PLAIN_CHARSET = OUString::createFromAscii( "text/plain;charset=" ); 80 const OUString HPNAME_OEM_ANSI_TEXT = OUString::createFromAscii( "OEM/ANSI Text" ); 81 82 const OUString HTML_FORMAT_NAME_WINDOWS = OUString::createFromAscii( "HTML Format" ); 83 const OUString HTML_FORMAT_NAME_SOFFICE = OUString::createFromAscii( "HTML (HyperText Markup Language)" ); 84 85 //------------------------------------------------------------------------ 86 // 87 //------------------------------------------------------------------------ 88 89 CDataFormatTranslator::CDataFormatTranslator( const Reference< XMultiServiceFactory >& aServiceManager ) : 90 m_SrvMgr( aServiceManager ) 91 { 92 m_XDataFormatTranslator = Reference< XDataFormatTranslator >( 93 m_SrvMgr->createInstance( OUString::createFromAscii( "com.sun.star.datatransfer.DataFormatTranslator" ) ), UNO_QUERY ); 94 } 95 96 //------------------------------------------------------------------------ 97 // 98 //------------------------------------------------------------------------ 99 100 CFormatEtc CDataFormatTranslator::getFormatEtcFromDataFlavor( const DataFlavor& aDataFlavor ) const 101 { 102 sal_Int32 cf = CF_INVALID; 103 104 try 105 { 106 if( m_XDataFormatTranslator.is( ) ) 107 { 108 Any aFormat = m_XDataFormatTranslator->getSystemDataTypeFromDataFlavor( aDataFlavor ); 109 110 if ( aFormat.hasValue( ) ) 111 { 112 if ( aFormat.getValueType( ) == CPPUTYPE_SALINT32 ) 113 { 114 aFormat >>= cf; 115 OSL_ENSURE( CF_INVALID != cf, "Invalid Clipboard format delivered" ); 116 } 117 else if ( aFormat.getValueType( ) == CPPUTYPE_OUSTRING ) 118 { 119 OUString aClipFmtName; 120 aFormat >>= aClipFmtName; 121 122 OSL_ASSERT( aClipFmtName.getLength( ) ); 123 cf = RegisterClipboardFormatW( reinterpret_cast<LPCWSTR>(aClipFmtName.getStr( )) ); 124 125 OSL_ENSURE( CF_INVALID != cf, "RegisterClipboardFormat failed" ); 126 } 127 else 128 OSL_ENSURE( sal_False, "Wrong Any-Type detected" ); 129 } 130 } 131 } 132 catch( ... ) 133 { 134 OSL_ENSURE( sal_False, "Unexpected error" ); 135 } 136 137 return sal::static_int_cast<CFormatEtc>(getFormatEtcForClipformat( sal::static_int_cast<CLIPFORMAT>(cf) )); 138 } 139 140 //------------------------------------------------------------------------ 141 // 142 //------------------------------------------------------------------------ 143 144 DataFlavor CDataFormatTranslator::getDataFlavorFromFormatEtc( const FORMATETC& aFormatEtc, LCID lcid ) const 145 { 146 DataFlavor aFlavor; 147 148 try 149 { 150 CLIPFORMAT aClipformat = aFormatEtc.cfFormat; 151 152 Any aAny; 153 aAny <<= static_cast< sal_Int32 >( aClipformat ); 154 155 if ( isOemOrAnsiTextFormat( aClipformat ) ) 156 { 157 aFlavor.MimeType = TEXT_PLAIN_CHARSET; 158 aFlavor.MimeType += getTextCharsetFromLCID( lcid, aClipformat ); 159 160 aFlavor.HumanPresentableName = HPNAME_OEM_ANSI_TEXT; 161 aFlavor.DataType = CPPUTYPE_SEQSALINT8; 162 } 163 else if ( CF_INVALID != aClipformat ) 164 { 165 if ( m_XDataFormatTranslator.is( ) ) 166 { 167 aFlavor = m_XDataFormatTranslator->getDataFlavorFromSystemDataType( aAny ); 168 169 if ( !aFlavor.MimeType.getLength( ) ) 170 { 171 // lookup of DataFlavor from clipboard format id 172 // failed, so we try to resolve via clipboard 173 // format name 174 OUString clipFormatName = getClipboardFormatName( aClipformat ); 175 176 // if we could not get a clipboard format name an 177 // error must have occured or it is a standard 178 // clipboard format that we don't translate, e.g. 179 // CF_BITMAP (the office only uses CF_DIB) 180 if ( clipFormatName.getLength( ) ) 181 { 182 aAny <<= clipFormatName; 183 aFlavor = m_XDataFormatTranslator->getDataFlavorFromSystemDataType( aAny ); 184 } 185 } 186 } 187 } 188 } 189 catch( ... ) 190 { 191 OSL_ENSURE( sal_False, "Unexpected error" ); 192 } 193 194 return aFlavor; 195 } 196 197 //------------------------------------------------------------------------ 198 // 199 //------------------------------------------------------------------------ 200 201 CFormatEtc SAL_CALL CDataFormatTranslator::getFormatEtcForClipformatName( const OUString& aClipFmtName ) const 202 { 203 // check parameter 204 if ( !aClipFmtName.getLength( ) ) 205 return CFormatEtc( CF_INVALID ); 206 207 CLIPFORMAT cf = sal::static_int_cast<CLIPFORMAT>(RegisterClipboardFormatW( reinterpret_cast<LPCWSTR>(aClipFmtName.getStr( )) )); 208 return getFormatEtcForClipformat( cf ); 209 } 210 211 //------------------------------------------------------------------------ 212 // 213 //------------------------------------------------------------------------ 214 215 OUString CDataFormatTranslator::getClipboardFormatName( CLIPFORMAT aClipformat ) const 216 { 217 OSL_PRECOND( CF_INVALID != aClipformat, "Invalid clipboard format" ); 218 219 sal_Unicode wBuff[ MAX_CLIPFORMAT_NAME ]; 220 sal_Int32 nLen = GetClipboardFormatNameW( aClipformat, reinterpret_cast<LPWSTR>(wBuff), MAX_CLIPFORMAT_NAME ); 221 222 return OUString( wBuff, nLen ); 223 } 224 225 //------------------------------------------------------------------------ 226 // 227 //------------------------------------------------------------------------ 228 229 CFormatEtc SAL_CALL CDataFormatTranslator::getFormatEtcForClipformat( CLIPFORMAT cf ) const 230 { 231 CFormatEtc fetc( cf, TYMED_NULL, NULL, DVASPECT_CONTENT ); 232 233 switch( cf ) 234 { 235 case CF_METAFILEPICT: 236 fetc.setTymed( TYMED_MFPICT ); 237 break; 238 239 case CF_ENHMETAFILE: 240 fetc.setTymed( TYMED_ENHMF ); 241 break; 242 243 default: 244 fetc.setTymed( TYMED_HGLOBAL /*| TYMED_ISTREAM*/ ); 245 } 246 247 /* 248 hack: in order to paste urls copied by Internet Explorer 249 with "copy link" we set the lindex member to 0 250 but if we really want to support CFSTR_FILECONTENT and 251 the accompany format CFSTR_FILEDESCRIPTOR (FileGroupDescriptor) 252 the client of the clipboard service has to provide a id 253 of which FileContents it wants to paste 254 see MSDN: "Handling Shell Data Transfer Scenarios" 255 */ 256 if ( cf == RegisterClipboardFormatA( CFSTR_FILECONTENTS ) ) 257 fetc.setLindex( 0 ); 258 259 return fetc; 260 } 261 262 //------------------------------------------------------------------------ 263 // 264 //------------------------------------------------------------------------ 265 266 sal_Bool SAL_CALL CDataFormatTranslator::isOemOrAnsiTextFormat( CLIPFORMAT cf ) const 267 { 268 return ( (cf == CF_TEXT) || (cf == CF_OEMTEXT) ); 269 } 270 271 //------------------------------------------------------------------------ 272 // 273 //------------------------------------------------------------------------ 274 275 sal_Bool SAL_CALL CDataFormatTranslator::isUnicodeTextFormat( CLIPFORMAT cf ) const 276 { 277 return ( cf == CF_UNICODETEXT ); 278 } 279 280 //------------------------------------------------------------------------ 281 // 282 //------------------------------------------------------------------------ 283 284 sal_Bool SAL_CALL CDataFormatTranslator::isTextFormat( CLIPFORMAT cf ) const 285 { 286 return ( isOemOrAnsiTextFormat( cf ) || isUnicodeTextFormat( cf ) ); 287 } 288 289 //------------------------------------------------------------------------ 290 // 291 //------------------------------------------------------------------------ 292 293 sal_Bool SAL_CALL CDataFormatTranslator::isHTMLFormat( CLIPFORMAT cf ) const 294 { 295 OUString clipFormatName = getClipboardFormatName( cf ); 296 return ( clipFormatName == HTML_FORMAT_NAME_WINDOWS ); 297 } 298 299 //------------------------------------------------------------------------ 300 // 301 //------------------------------------------------------------------------ 302 303 sal_Bool SAL_CALL CDataFormatTranslator::isTextHtmlFormat( CLIPFORMAT cf ) const 304 { 305 OUString clipFormatName = getClipboardFormatName( cf ); 306 return ( clipFormatName.equalsIgnoreAsciiCase( HTML_FORMAT_NAME_SOFFICE ) ); 307 } 308 309 //------------------------------------------------------------------------ 310 // 311 //------------------------------------------------------------------------ 312 313 OUString SAL_CALL CDataFormatTranslator::getTextCharsetFromLCID( LCID lcid, CLIPFORMAT aClipformat ) const 314 { 315 OSL_ASSERT( isOemOrAnsiTextFormat( aClipformat ) ); 316 317 OUString charset; 318 if ( CF_TEXT == aClipformat ) 319 { 320 charset = getMimeCharsetFromLocaleId( 321 lcid, 322 LOCALE_IDEFAULTANSICODEPAGE, 323 PRE_WINDOWS_CODEPAGE ); 324 } 325 else if ( CF_OEMTEXT == aClipformat ) 326 { 327 charset = getMimeCharsetFromLocaleId( 328 lcid, 329 LOCALE_IDEFAULTCODEPAGE, 330 PRE_OEM_CODEPAGE ); 331 } 332 else // CF_UNICODE 333 OSL_ASSERT( sal_False ); 334 335 return charset; 336 } 337