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 for ( sal_uInt32 i = 0; i < aNum; i++, nFetched++, lpFetc++, ++m_EnumIterator ) 147 { 148 if ( m_EnumIterator == m_FormatMap.end() ) 149 break; 150 CopyFormatEtc( lpFetc, *m_EnumIterator ); 151 } 152 153 return nFetched; 154 } 155 156 157 //------------------------------------------------------------------------ 158 // 159 //------------------------------------------------------------------------ 160 161 sal_Bool SAL_CALL CFormatEtcContainer::skipFormatEtc( sal_uInt32 aNum ) 162 { 163 FormatEtcMap_t::const_iterator iter_end = m_FormatMap.end( ); 164 for ( sal_uInt32 i = 0; 165 (i < aNum) && (m_EnumIterator != iter_end); 166 i++, ++m_EnumIterator ) 167 ;/* intentionally left empty */ 168 169 return ( m_EnumIterator != m_FormatMap.end( ) ); 170 } 171 172 173 //######################################################################### 174 175 176 //------------------------------------------------------------------------ 177 // 178 //------------------------------------------------------------------------ 179 180 CFormatRegistrar::CFormatRegistrar( const Reference< XMultiServiceFactory >& ServiceManager, 181 const CDataFormatTranslator& aDataFormatTranslator ) : 182 m_DataFormatTranslator( aDataFormatTranslator ), 183 m_bHasSynthesizedLocale( sal_False ), 184 m_SrvMgr( ServiceManager ) 185 { 186 } 187 188 // ---------------------------------------------------------------------------------------- 189 // this function converts all DataFlavors of the given FlavorList into 190 // an appropriate FORMATETC structure, for some formats like unicodetext, 191 // text and text/html we will offer an accompany format e.g.: 192 // 193 // DataFlavor | Registered Clipformat | Registered accompany clipformat 194 // -------------------------|---------------------------|----------------------------------- 195 // text/plain;charset=ansi | CF_TEXT | CF_UNICODETEXT 196 // | | CF_LOCALE (if charset != GetACP() 197 // | | 198 // text/plain;charset=oem | CF_OEMTEXT | CF_UNICODETEXT 199 // | | CF_LOCALE (if charset != GetOEMCP() 200 // | | 201 // text/plain;charset=utf-16| CF_UNICODETEXT | CF_TEXT 202 // | | 203 // text/html | HTML (Hypertext ...) | HTML Format 204 // | | 205 // 206 // if some tries to register different text formats with different charsets the last 207 // registered wins and the others are ignored 208 // ---------------------------------------------------------------------------------------- 209 210 void SAL_CALL CFormatRegistrar::RegisterFormats( 211 const Reference< XTransferable >& aXTransferable, CFormatEtcContainer& aFormatEtcContainer ) 212 { 213 Sequence< DataFlavor > aFlavorList = aXTransferable->getTransferDataFlavors( ); 214 sal_Int32 nFlavors = aFlavorList.getLength( ); 215 sal_Bool bUnicodeRegistered = sal_False; 216 DataFlavor aFlavor; 217 218 for( sal_Int32 i = 0; i < nFlavors; i++ ) 219 { 220 aFlavor = aFlavorList[i]; 221 CFormatEtc fetc = m_DataFormatTranslator.getFormatEtcFromDataFlavor( aFlavor ); 222 223 // maybe an internal format so we ignore it 224 if ( CF_INVALID == fetc.getClipformat( ) ) 225 continue; 226 227 if ( !needsToSynthesizeAccompanyFormats( fetc ) ) 228 aFormatEtcContainer.addFormatEtc( fetc ); 229 else 230 { 231 // if we haven't registered any text format up to now 232 if ( m_DataFormatTranslator.isTextFormat( fetc.getClipformat() ) && !bUnicodeRegistered ) 233 { 234 // if the transferable supports unicode text we ignore 235 // any further text format the transferable offers 236 // because we can create it from Unicode text in addition 237 // we register CF_TEXT for non unicode clients 238 if ( m_DataFormatTranslator.isUnicodeTextFormat( fetc.getClipformat() ) ) 239 { 240 aFormatEtcContainer.addFormatEtc( fetc ); // add CF_UNICODE 241 aFormatEtcContainer.addFormatEtc( 242 m_DataFormatTranslator.getFormatEtcForClipformat( CF_TEXT ) ); // add CF_TEXT 243 bUnicodeRegistered = sal_True; 244 } 245 else if ( !hasUnicodeFlavor( aXTransferable ) ) 246 { 247 // we try to investigate the charset and make a valid 248 // windows codepage from this charset the default 249 // return value is the result of GetACP( ) 250 OUString charset = getCharsetFromDataFlavor( aFlavor ); 251 sal_uInt32 txtCP = getWinCPFromMimeCharset( charset ); 252 253 // we try to get a Locale appropriate for this codepage 254 if ( findLocaleForTextCodePage( ) ) 255 { 256 m_TxtCodePage = txtCP; 257 258 aFormatEtcContainer.addFormatEtc( 259 m_DataFormatTranslator.getFormatEtcForClipformat( CF_UNICODETEXT ) ); 260 261 if ( !IsOEMCP( m_TxtCodePage ) ) 262 aFormatEtcContainer.addFormatEtc( 263 m_DataFormatTranslator.getFormatEtcForClipformat( CF_TEXT ) ); 264 else 265 aFormatEtcContainer.addFormatEtc( 266 m_DataFormatTranslator.getFormatEtcForClipformat( CF_OEMTEXT ) ); 267 268 aFormatEtcContainer.addFormatEtc( 269 m_DataFormatTranslator.getFormatEtcForClipformat( CF_LOCALE ) ); 270 271 // we save the flavor so it's easier when 272 // queried for it in XTDataObject::GetData(...) 273 m_RegisteredTextFlavor = aFlavor; 274 m_bHasSynthesizedLocale = sal_True; 275 } 276 } 277 } 278 else if ( m_DataFormatTranslator.isTextHtmlFormat( fetc.getClipformat( ) ) ) // Html (Hyper Text...) 279 { 280 // we add text/html ( HTML (HyperText Markup Language) ) 281 aFormatEtcContainer.addFormatEtc( fetc ); 282 283 // and HTML Format 284 OUString htmlFormat( OUString::createFromAscii( "HTML Format" ) ); 285 aFormatEtcContainer.addFormatEtc( 286 m_DataFormatTranslator.getFormatEtcForClipformatName( htmlFormat ) ); 287 } 288 } 289 } 290 } 291 292 //------------------------------------------------------------------------ 293 // 294 //------------------------------------------------------------------------ 295 296 sal_Bool SAL_CALL CFormatRegistrar::hasSynthesizedLocale( ) const 297 { 298 return m_bHasSynthesizedLocale; 299 } 300 301 //------------------------------------------------------------------------ 302 // 303 //------------------------------------------------------------------------ 304 305 LCID SAL_CALL CFormatRegistrar::getSynthesizedLocale( ) const 306 { 307 return m_TxtLocale; 308 } 309 310 //------------------------------------------------------------------------ 311 // 312 //------------------------------------------------------------------------ 313 314 sal_uInt32 SAL_CALL CFormatRegistrar::getRegisteredTextCodePage( ) const 315 { 316 return m_TxtCodePage; 317 } 318 319 //------------------------------------------------------------------------ 320 // 321 //------------------------------------------------------------------------ 322 323 DataFlavor SAL_CALL CFormatRegistrar::getRegisteredTextFlavor( ) const 324 { 325 return m_RegisteredTextFlavor; 326 } 327 328 //------------------------------------------------------------------------ 329 // 330 //------------------------------------------------------------------------ 331 332 sal_Bool SAL_CALL CFormatRegistrar::isSynthesizeableFormat( const CFormatEtc& aFormatEtc ) const 333 { 334 return ( m_DataFormatTranslator.isOemOrAnsiTextFormat( aFormatEtc.getClipformat() ) || 335 m_DataFormatTranslator.isUnicodeTextFormat( aFormatEtc.getClipformat() ) || 336 m_DataFormatTranslator.isHTMLFormat( aFormatEtc.getClipformat() ) ); 337 } 338 339 //------------------------------------------------------------------------ 340 // 341 //------------------------------------------------------------------------ 342 343 inline 344 sal_Bool SAL_CALL CFormatRegistrar::needsToSynthesizeAccompanyFormats( const CFormatEtc& aFormatEtc ) const 345 { 346 return ( m_DataFormatTranslator.isOemOrAnsiTextFormat( aFormatEtc.getClipformat() ) || 347 m_DataFormatTranslator.isUnicodeTextFormat( aFormatEtc.getClipformat() ) || 348 m_DataFormatTranslator.isTextHtmlFormat( aFormatEtc.getClipformat( ) ) ); 349 } 350 351 //------------------------------------------------------------------------ 352 // 353 //------------------------------------------------------------------------ 354 355 OUString SAL_CALL CFormatRegistrar::getCharsetFromDataFlavor( const DataFlavor& aFlavor ) 356 { 357 OUString charset; 358 359 try 360 { 361 Reference< XMimeContentTypeFactory > xMimeFac( 362 m_SrvMgr->createInstance( OUString::createFromAscii( \ 363 "com.sun.star.datatransfer.MimeContentTypeFactory" ) ), UNO_QUERY ); 364 365 if( xMimeFac.is( ) ) 366 { 367 Reference< XMimeContentType > xMimeType( xMimeFac->createMimeContentType( aFlavor.MimeType ) ); 368 if ( xMimeType->hasParameter( TEXTPLAIN_PARAM_CHARSET ) ) 369 charset = xMimeType->getParameterValue( TEXTPLAIN_PARAM_CHARSET ); 370 else 371 charset = getMimeCharsetFromWinCP( GetACP( ), PRE_WINDOWS_CODEPAGE ); 372 } 373 } 374 catch(NoSuchElementException&) 375 { 376 OSL_ENSURE( sal_False, "Unexpected" ); 377 } 378 catch(...) 379 { 380 OSL_ENSURE( sal_False, "Invalid data flavor" ); 381 } 382 383 return charset; 384 } 385 386 //------------------------------------------------------------------------ 387 // 388 //------------------------------------------------------------------------ 389 390 sal_Bool SAL_CALL CFormatRegistrar::hasUnicodeFlavor( const Reference< XTransferable >& aXTransferable ) const 391 { 392 CFormatEtc fetc( CF_UNICODETEXT ); 393 394 DataFlavor aFlavor = 395 m_DataFormatTranslator.getDataFlavorFromFormatEtc( fetc ); 396 397 return aXTransferable->isDataFlavorSupported( aFlavor ); 398 } 399 400 //------------------------------------------------------------------------ 401 // 402 //------------------------------------------------------------------------ 403 404 inline 405 sal_Bool CFormatRegistrar::isEqualCurrentSystemCodePage( sal_uInt32 aCodePage ) const 406 { 407 return ( (aCodePage == GetOEMCP()) || (aCodePage == GetACP()) ); 408 } 409 410 //------------------------------------------------------------------------ 411 // 412 //------------------------------------------------------------------------ 413 414 sal_Bool SAL_CALL CFormatRegistrar::findLocaleForTextCodePage( ) 415 { 416 m_TxtLocale = 0; 417 EnumSystemLocalesA( CFormatRegistrar::EnumLocalesProc, LCID_INSTALLED ); 418 return ( IsValidLocale( m_TxtLocale, LCID_INSTALLED ) ) ? sal_True : sal_False; 419 } 420 421 //------------------------------------------------------------------------ 422 // 423 //------------------------------------------------------------------------ 424 425 sal_Bool SAL_CALL CFormatRegistrar::isLocaleCodePage( LCID lcid, LCTYPE lctype, sal_uInt32 codepage ) 426 { 427 char buff[6]; 428 sal_uInt32 localeCodePage; 429 430 OSL_ASSERT( IsValidLocale( lcid, LCID_INSTALLED ) ); 431 432 // get the ansi codepage of the current locale 433 GetLocaleInfoA( lcid, lctype, buff, sizeof( buff ) ); 434 localeCodePage = atol( buff ); 435 436 return ( localeCodePage == codepage ); 437 } 438 439 //------------------------------------------------------------------------ 440 // 441 //------------------------------------------------------------------------ 442 443 inline 444 sal_Bool SAL_CALL CFormatRegistrar::isLocaleOemCodePage( LCID lcid, sal_uInt32 codepage ) 445 { 446 return isLocaleCodePage( lcid, LOCALE_IDEFAULTCODEPAGE, codepage ); 447 } 448 449 //------------------------------------------------------------------------ 450 // 451 //------------------------------------------------------------------------ 452 453 inline 454 sal_Bool SAL_CALL CFormatRegistrar::isLocaleAnsiCodePage( LCID lcid, sal_uInt32 codepage ) 455 { 456 return isLocaleCodePage( lcid, LOCALE_IDEFAULTANSICODEPAGE, codepage ); 457 } 458 459 //------------------------------------------------------------------------ 460 // 461 //------------------------------------------------------------------------ 462 463 BOOL CALLBACK CFormatRegistrar::EnumLocalesProc( LPSTR lpLocaleStr ) 464 { 465 // the lpLocaleStr parametere is hexadecimal 466 LCID lcid = strtol( lpLocaleStr, NULL, 16 ); 467 468 if ( isLocaleAnsiCodePage( lcid, CFormatRegistrar::m_TxtCodePage ) || 469 isLocaleOemCodePage( lcid, CFormatRegistrar::m_TxtCodePage ) ) 470 { 471 CFormatRegistrar::m_TxtLocale = lcid; 472 return sal_False; // stop enumerating 473 } 474 475 return sal_True; 476 } 477 478