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