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 <osl/diagnose.h> 31 #include "FetcList.hxx" 32 #include "Fetc.hxx" 33 #include <com/sun/star/datatransfer/XMimeContentTypeFactory.hpp> 34 #include <com/sun/star/datatransfer/XMimeContentType.hpp> 35 36 #ifndef _DATAFORMATTRANSLATOR_HXX_ 37 #include "DataFmtTransl.hxx" 38 #endif 39 #include "..\misc\ImplHelper.hxx" 40 #include "..\misc\WinClip.hxx" 41 42 #include <algorithm> 43 44 #include "MimeAttrib.hxx" 45 46 //------------------------------------------------------------------------ 47 // namespace directives 48 //------------------------------------------------------------------------ 49 50 using namespace com::sun::star::uno; 51 using namespace com::sun::star::datatransfer; 52 using namespace com::sun::star::lang; 53 using namespace com::sun::star::container; 54 using namespace rtl; 55 using namespace std; 56 57 //------------------------------------------------------------------------ 58 // 59 //------------------------------------------------------------------------ 60 61 LCID CFormatRegistrar::m_TxtLocale = 0; 62 sal_uInt32 CFormatRegistrar::m_TxtCodePage = GetACP( ); 63 64 //------------------------------------------------------------------------ 65 // 66 //------------------------------------------------------------------------ 67 68 CFormatEtcContainer::CFormatEtcContainer( ) 69 { 70 m_EnumIterator = m_FormatMap.begin( ); 71 } 72 73 //------------------------------------------------------------------------ 74 // 75 //------------------------------------------------------------------------ 76 77 void CFormatEtcContainer::addFormatEtc( const CFormatEtc& fetc ) 78 { 79 m_FormatMap.push_back( CFormatEtc( fetc ) ); 80 } 81 82 //------------------------------------------------------------------------ 83 // 84 //------------------------------------------------------------------------ 85 86 void SAL_CALL CFormatEtcContainer::removeFormatEtc( const CFormatEtc& fetc ) 87 { 88 FormatEtcMap_t::iterator iter = 89 find( m_FormatMap.begin(), m_FormatMap.end(), fetc ); 90 91 if ( iter != m_FormatMap.end( ) ) 92 m_FormatMap.erase( iter ); 93 } 94 95 //------------------------------------------------------------------------ 96 // 97 //------------------------------------------------------------------------ 98 99 void SAL_CALL CFormatEtcContainer::removeAllFormatEtc( ) 100 { 101 m_FormatMap.clear( ); 102 } 103 104 //------------------------------------------------------------------------ 105 // 106 //------------------------------------------------------------------------ 107 108 sal_Bool CFormatEtcContainer::hasFormatEtc( const CFormatEtc& fetc ) const 109 { 110 FormatEtcMap_t::const_iterator iter = 111 find( m_FormatMap.begin(), m_FormatMap.end(), fetc ); 112 113 return ( iter != m_FormatMap.end( ) ); 114 } 115 116 //------------------------------------------------------------------------ 117 // 118 //------------------------------------------------------------------------ 119 120 sal_Bool CFormatEtcContainer::hasElements( ) const 121 { 122 return ( m_FormatMap.size( ) > 0 ); 123 } 124 125 //------------------------------------------------------------------------ 126 // 127 //------------------------------------------------------------------------ 128 129 void CFormatEtcContainer::beginEnumFormatEtc( ) 130 { 131 m_EnumIterator = m_FormatMap.begin( ); 132 } 133 134 //------------------------------------------------------------------------ 135 // 136 //------------------------------------------------------------------------ 137 138 sal_uInt32 SAL_CALL CFormatEtcContainer::nextFormatEtc( LPFORMATETC lpFetc, 139 sal_uInt32 aNum ) 140 { 141 OSL_ASSERT( lpFetc ); 142 OSL_ASSERT( !IsBadWritePtr( lpFetc, sizeof( FORMATETC ) * aNum ) ); 143 144 sal_uInt32 nFetched = 0; 145 146 if ( m_EnumIterator != m_FormatMap.end( ) ) 147 { 148 for ( sal_uInt32 i = 0; i < aNum; i++, nFetched++, lpFetc++, ++m_EnumIterator ) 149 CopyFormatEtc( lpFetc, *m_EnumIterator ); 150 } 151 152 return nFetched; 153 } 154 155 156 //------------------------------------------------------------------------ 157 // 158 //------------------------------------------------------------------------ 159 160 sal_Bool SAL_CALL CFormatEtcContainer::skipFormatEtc( sal_uInt32 aNum ) 161 { 162 FormatEtcMap_t::const_iterator iter_end = m_FormatMap.end( ); 163 for ( sal_uInt32 i = 0; 164 (i < aNum) && (m_EnumIterator != iter_end); 165 i++, ++m_EnumIterator ) 166 ;/* intentionally left empty */ 167 168 return ( m_EnumIterator != m_FormatMap.end( ) ); 169 } 170 171 172 //######################################################################### 173 174 175 //------------------------------------------------------------------------ 176 // 177 //------------------------------------------------------------------------ 178 179 CFormatRegistrar::CFormatRegistrar( const Reference< XMultiServiceFactory >& ServiceManager, 180 const CDataFormatTranslator& aDataFormatTranslator ) : 181 m_DataFormatTranslator( aDataFormatTranslator ), 182 m_bHasSynthesizedLocale( sal_False ), 183 m_SrvMgr( ServiceManager ) 184 { 185 } 186 187 // ---------------------------------------------------------------------------------------- 188 // this function converts all DataFlavors of the given FlavorList into 189 // an appropriate FORMATETC structure, for some formats like unicodetext, 190 // text and text/html we will offer an accompany format e.g.: 191 // 192 // DataFlavor | Registered Clipformat | Registered accompany clipformat 193 // -------------------------|---------------------------|----------------------------------- 194 // text/plain;charset=ansi | CF_TEXT | CF_UNICODETEXT 195 // | | CF_LOCALE (if charset != GetACP() 196 // | | 197 // text/plain;charset=oem | CF_OEMTEXT | CF_UNICODETEXT 198 // | | CF_LOCALE (if charset != GetOEMCP() 199 // | | 200 // text/plain;charset=utf-16| CF_UNICODETEXT | CF_TEXT 201 // | | 202 // text/html | HTML (Hypertext ...) | HTML Format 203 // | | 204 // 205 // if some tries to register different text formats with different charsets the last 206 // registered wins and the others are ignored 207 // ---------------------------------------------------------------------------------------- 208 209 void SAL_CALL CFormatRegistrar::RegisterFormats( 210 const Reference< XTransferable >& aXTransferable, CFormatEtcContainer& aFormatEtcContainer ) 211 { 212 Sequence< DataFlavor > aFlavorList = aXTransferable->getTransferDataFlavors( ); 213 sal_Int32 nFlavors = aFlavorList.getLength( ); 214 sal_Bool bUnicodeRegistered = sal_False; 215 DataFlavor aFlavor; 216 217 for( sal_Int32 i = 0; i < nFlavors; i++ ) 218 { 219 aFlavor = aFlavorList[i]; 220 CFormatEtc fetc = m_DataFormatTranslator.getFormatEtcFromDataFlavor( aFlavor ); 221 222 // maybe an internal format so we ignore it 223 if ( CF_INVALID == fetc.getClipformat( ) ) 224 continue; 225 226 if ( !needsToSynthesizeAccompanyFormats( fetc ) ) 227 aFormatEtcContainer.addFormatEtc( fetc ); 228 else 229 { 230 // if we haven't registered any text format up to now 231 if ( m_DataFormatTranslator.isTextFormat( fetc.getClipformat() ) && !bUnicodeRegistered ) 232 { 233 // if the transferable supports unicode text we ignore 234 // any further text format the transferable offers 235 // because we can create it from Unicode text in addition 236 // we register CF_TEXT for non unicode clients 237 if ( m_DataFormatTranslator.isUnicodeTextFormat( fetc.getClipformat() ) ) 238 { 239 aFormatEtcContainer.addFormatEtc( fetc ); // add CF_UNICODE 240 aFormatEtcContainer.addFormatEtc( 241 m_DataFormatTranslator.getFormatEtcForClipformat( CF_TEXT ) ); // add CF_TEXT 242 bUnicodeRegistered = sal_True; 243 } 244 else if ( !hasUnicodeFlavor( aXTransferable ) ) 245 { 246 // we try to investigate the charset and make a valid 247 // windows codepage from this charset the default 248 // return value is the result of GetACP( ) 249 OUString charset = getCharsetFromDataFlavor( aFlavor ); 250 sal_uInt32 txtCP = getWinCPFromMimeCharset( charset ); 251 252 // we try to get a Locale appropriate for this codepage 253 if ( findLocaleForTextCodePage( ) ) 254 { 255 m_TxtCodePage = txtCP; 256 257 aFormatEtcContainer.addFormatEtc( 258 m_DataFormatTranslator.getFormatEtcForClipformat( CF_UNICODETEXT ) ); 259 260 if ( !IsOEMCP( m_TxtCodePage ) ) 261 aFormatEtcContainer.addFormatEtc( 262 m_DataFormatTranslator.getFormatEtcForClipformat( CF_TEXT ) ); 263 else 264 aFormatEtcContainer.addFormatEtc( 265 m_DataFormatTranslator.getFormatEtcForClipformat( CF_OEMTEXT ) ); 266 267 aFormatEtcContainer.addFormatEtc( 268 m_DataFormatTranslator.getFormatEtcForClipformat( CF_LOCALE ) ); 269 270 // we save the flavor so it's easier when 271 // queried for it in XTDataObject::GetData(...) 272 m_RegisteredTextFlavor = aFlavor; 273 m_bHasSynthesizedLocale = sal_True; 274 } 275 } 276 } 277 else if ( m_DataFormatTranslator.isTextHtmlFormat( fetc.getClipformat( ) ) ) // Html (Hyper Text...) 278 { 279 // we add text/html ( HTML (HyperText Markup Language) ) 280 aFormatEtcContainer.addFormatEtc( fetc ); 281 282 // and HTML Format 283 OUString htmlFormat( OUString::createFromAscii( "HTML Format" ) ); 284 aFormatEtcContainer.addFormatEtc( 285 m_DataFormatTranslator.getFormatEtcForClipformatName( htmlFormat ) ); 286 } 287 } 288 } 289 } 290 291 //------------------------------------------------------------------------ 292 // 293 //------------------------------------------------------------------------ 294 295 sal_Bool SAL_CALL CFormatRegistrar::hasSynthesizedLocale( ) const 296 { 297 return m_bHasSynthesizedLocale; 298 } 299 300 //------------------------------------------------------------------------ 301 // 302 //------------------------------------------------------------------------ 303 304 LCID SAL_CALL CFormatRegistrar::getSynthesizedLocale( ) const 305 { 306 return m_TxtLocale; 307 } 308 309 //------------------------------------------------------------------------ 310 // 311 //------------------------------------------------------------------------ 312 313 sal_uInt32 SAL_CALL CFormatRegistrar::getRegisteredTextCodePage( ) const 314 { 315 return m_TxtCodePage; 316 } 317 318 //------------------------------------------------------------------------ 319 // 320 //------------------------------------------------------------------------ 321 322 DataFlavor SAL_CALL CFormatRegistrar::getRegisteredTextFlavor( ) const 323 { 324 return m_RegisteredTextFlavor; 325 } 326 327 //------------------------------------------------------------------------ 328 // 329 //------------------------------------------------------------------------ 330 331 sal_Bool SAL_CALL CFormatRegistrar::isSynthesizeableFormat( const CFormatEtc& aFormatEtc ) const 332 { 333 return ( m_DataFormatTranslator.isOemOrAnsiTextFormat( aFormatEtc.getClipformat() ) || 334 m_DataFormatTranslator.isUnicodeTextFormat( aFormatEtc.getClipformat() ) || 335 m_DataFormatTranslator.isHTMLFormat( aFormatEtc.getClipformat() ) ); 336 } 337 338 //------------------------------------------------------------------------ 339 // 340 //------------------------------------------------------------------------ 341 342 inline 343 sal_Bool SAL_CALL CFormatRegistrar::needsToSynthesizeAccompanyFormats( const CFormatEtc& aFormatEtc ) const 344 { 345 return ( m_DataFormatTranslator.isOemOrAnsiTextFormat( aFormatEtc.getClipformat() ) || 346 m_DataFormatTranslator.isUnicodeTextFormat( aFormatEtc.getClipformat() ) || 347 m_DataFormatTranslator.isTextHtmlFormat( aFormatEtc.getClipformat( ) ) ); 348 } 349 350 //------------------------------------------------------------------------ 351 // 352 //------------------------------------------------------------------------ 353 354 OUString SAL_CALL CFormatRegistrar::getCharsetFromDataFlavor( const DataFlavor& aFlavor ) 355 { 356 OUString charset; 357 358 try 359 { 360 Reference< XMimeContentTypeFactory > xMimeFac( 361 m_SrvMgr->createInstance( OUString::createFromAscii( \ 362 "com.sun.star.datatransfer.MimeContentTypeFactory" ) ), UNO_QUERY ); 363 364 if( xMimeFac.is( ) ) 365 { 366 Reference< XMimeContentType > xMimeType( xMimeFac->createMimeContentType( aFlavor.MimeType ) ); 367 if ( xMimeType->hasParameter( TEXTPLAIN_PARAM_CHARSET ) ) 368 charset = xMimeType->getParameterValue( TEXTPLAIN_PARAM_CHARSET ); 369 else 370 charset = getMimeCharsetFromWinCP( GetACP( ), PRE_WINDOWS_CODEPAGE ); 371 } 372 } 373 catch(NoSuchElementException&) 374 { 375 OSL_ENSURE( sal_False, "Unexpected" ); 376 } 377 catch(...) 378 { 379 OSL_ENSURE( sal_False, "Invalid data flavor" ); 380 } 381 382 return charset; 383 } 384 385 //------------------------------------------------------------------------ 386 // 387 //------------------------------------------------------------------------ 388 389 sal_Bool SAL_CALL CFormatRegistrar::hasUnicodeFlavor( const Reference< XTransferable >& aXTransferable ) const 390 { 391 CFormatEtc fetc( CF_UNICODETEXT ); 392 393 DataFlavor aFlavor = 394 m_DataFormatTranslator.getDataFlavorFromFormatEtc( fetc ); 395 396 return aXTransferable->isDataFlavorSupported( aFlavor ); 397 } 398 399 //------------------------------------------------------------------------ 400 // 401 //------------------------------------------------------------------------ 402 403 inline 404 sal_Bool CFormatRegistrar::isEqualCurrentSystemCodePage( sal_uInt32 aCodePage ) const 405 { 406 return ( (aCodePage == GetOEMCP()) || (aCodePage == GetACP()) ); 407 } 408 409 //------------------------------------------------------------------------ 410 // 411 //------------------------------------------------------------------------ 412 413 sal_Bool SAL_CALL CFormatRegistrar::findLocaleForTextCodePage( ) 414 { 415 m_TxtLocale = 0; 416 EnumSystemLocalesA( CFormatRegistrar::EnumLocalesProc, LCID_INSTALLED ); 417 return ( IsValidLocale( m_TxtLocale, LCID_INSTALLED ) ) ? sal_True : sal_False; 418 } 419 420 //------------------------------------------------------------------------ 421 // 422 //------------------------------------------------------------------------ 423 424 sal_Bool SAL_CALL CFormatRegistrar::isLocaleCodePage( LCID lcid, LCTYPE lctype, sal_uInt32 codepage ) 425 { 426 char buff[6]; 427 sal_uInt32 localeCodePage; 428 429 OSL_ASSERT( IsValidLocale( lcid, LCID_INSTALLED ) ); 430 431 // get the ansi codepage of the current locale 432 GetLocaleInfoA( lcid, lctype, buff, sizeof( buff ) ); 433 localeCodePage = atol( buff ); 434 435 return ( localeCodePage == codepage ); 436 } 437 438 //------------------------------------------------------------------------ 439 // 440 //------------------------------------------------------------------------ 441 442 inline 443 sal_Bool SAL_CALL CFormatRegistrar::isLocaleOemCodePage( LCID lcid, sal_uInt32 codepage ) 444 { 445 return isLocaleCodePage( lcid, LOCALE_IDEFAULTCODEPAGE, codepage ); 446 } 447 448 //------------------------------------------------------------------------ 449 // 450 //------------------------------------------------------------------------ 451 452 inline 453 sal_Bool SAL_CALL CFormatRegistrar::isLocaleAnsiCodePage( LCID lcid, sal_uInt32 codepage ) 454 { 455 return isLocaleCodePage( lcid, LOCALE_IDEFAULTANSICODEPAGE, codepage ); 456 } 457 458 //------------------------------------------------------------------------ 459 // 460 //------------------------------------------------------------------------ 461 462 BOOL CALLBACK CFormatRegistrar::EnumLocalesProc( LPSTR lpLocaleStr ) 463 { 464 // the lpLocaleStr parametere is hexadecimal 465 LCID lcid = strtol( lpLocaleStr, NULL, 16 ); 466 467 if ( isLocaleAnsiCodePage( lcid, CFormatRegistrar::m_TxtCodePage ) || 468 isLocaleOemCodePage( lcid, CFormatRegistrar::m_TxtCodePage ) ) 469 { 470 CFormatRegistrar::m_TxtLocale = lcid; 471 return sal_False; // stop enumerating 472 } 473 474 return sal_True; 475 } 476 477