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