| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_dtrans.hxx" |
| |
| //------------------------------------------------------------------------ |
| // includes |
| //------------------------------------------------------------------------ |
| #include <osl/diagnose.h> |
| #include "FetcList.hxx" |
| #include "Fetc.hxx" |
| #include <com/sun/star/datatransfer/XMimeContentTypeFactory.hpp> |
| #include <com/sun/star/datatransfer/XMimeContentType.hpp> |
| |
| #ifndef _DATAFORMATTRANSLATOR_HXX_ |
| #include "DataFmtTransl.hxx" |
| #endif |
| #include "..\misc\ImplHelper.hxx" |
| #include "..\misc\WinClip.hxx" |
| |
| #include <algorithm> |
| |
| #include "MimeAttrib.hxx" |
| |
| //------------------------------------------------------------------------ |
| // namespace directives |
| //------------------------------------------------------------------------ |
| |
| using namespace com::sun::star::uno; |
| using namespace com::sun::star::datatransfer; |
| using namespace com::sun::star::lang; |
| using namespace com::sun::star::container; |
| using namespace rtl; |
| using namespace std; |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| LCID CFormatRegistrar::m_TxtLocale = 0; |
| sal_uInt32 CFormatRegistrar::m_TxtCodePage = GetACP( ); |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| CFormatEtcContainer::CFormatEtcContainer( ) |
| { |
| m_EnumIterator = m_FormatMap.begin( ); |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| void CFormatEtcContainer::addFormatEtc( const CFormatEtc& fetc ) |
| { |
| m_FormatMap.push_back( CFormatEtc( fetc ) ); |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| void SAL_CALL CFormatEtcContainer::removeFormatEtc( const CFormatEtc& fetc ) |
| { |
| FormatEtcMap_t::iterator iter = |
| find( m_FormatMap.begin(), m_FormatMap.end(), fetc ); |
| |
| if ( iter != m_FormatMap.end( ) ) |
| m_FormatMap.erase( iter ); |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| void SAL_CALL CFormatEtcContainer::removeAllFormatEtc( ) |
| { |
| m_FormatMap.clear( ); |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| sal_Bool CFormatEtcContainer::hasFormatEtc( const CFormatEtc& fetc ) const |
| { |
| FormatEtcMap_t::const_iterator iter = |
| find( m_FormatMap.begin(), m_FormatMap.end(), fetc ); |
| |
| return ( iter != m_FormatMap.end( ) ); |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| sal_Bool CFormatEtcContainer::hasElements( ) const |
| { |
| return ( m_FormatMap.size( ) > 0 ); |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| void CFormatEtcContainer::beginEnumFormatEtc( ) |
| { |
| m_EnumIterator = m_FormatMap.begin( ); |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| sal_uInt32 SAL_CALL CFormatEtcContainer::nextFormatEtc( LPFORMATETC lpFetc, |
| sal_uInt32 aNum ) |
| { |
| OSL_ASSERT( lpFetc ); |
| OSL_ASSERT( !IsBadWritePtr( lpFetc, sizeof( FORMATETC ) * aNum ) ); |
| |
| sal_uInt32 nFetched = 0; |
| |
| for ( sal_uInt32 i = 0; i < aNum; i++, nFetched++, lpFetc++, ++m_EnumIterator ) |
| { |
| if ( m_EnumIterator == m_FormatMap.end() ) |
| break; |
| CopyFormatEtc( lpFetc, *m_EnumIterator ); |
| } |
| |
| return nFetched; |
| } |
| |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| sal_Bool SAL_CALL CFormatEtcContainer::skipFormatEtc( sal_uInt32 aNum ) |
| { |
| FormatEtcMap_t::const_iterator iter_end = m_FormatMap.end( ); |
| for ( sal_uInt32 i = 0; |
| (i < aNum) && (m_EnumIterator != iter_end); |
| i++, ++m_EnumIterator ) |
| ;/* intentionally left empty */ |
| |
| return ( m_EnumIterator != m_FormatMap.end( ) ); |
| } |
| |
| |
| //######################################################################### |
| |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| CFormatRegistrar::CFormatRegistrar( const Reference< XMultiServiceFactory >& ServiceManager, |
| const CDataFormatTranslator& aDataFormatTranslator ) : |
| m_DataFormatTranslator( aDataFormatTranslator ), |
| m_bHasSynthesizedLocale( sal_False ), |
| m_SrvMgr( ServiceManager ) |
| { |
| } |
| |
| // ---------------------------------------------------------------------------------------- |
| // this function converts all DataFlavors of the given FlavorList into |
| // an appropriate FORMATETC structure, for some formats like unicodetext, |
| // text and text/html we will offer an accompany format e.g.: |
| // |
| // DataFlavor | Registered Clipformat | Registered accompany clipformat |
| // -------------------------|---------------------------|----------------------------------- |
| // text/plain;charset=ansi | CF_TEXT | CF_UNICODETEXT |
| // | | CF_LOCALE (if charset != GetACP() |
| // | | |
| // text/plain;charset=oem | CF_OEMTEXT | CF_UNICODETEXT |
| // | | CF_LOCALE (if charset != GetOEMCP() |
| // | | |
| // text/plain;charset=utf-16| CF_UNICODETEXT | CF_TEXT |
| // | | |
| // text/html | HTML (Hypertext ...) | HTML Format |
| // | | |
| // |
| // if some tries to register different text formats with different charsets the last |
| // registered wins and the others are ignored |
| // ---------------------------------------------------------------------------------------- |
| |
| void SAL_CALL CFormatRegistrar::RegisterFormats( |
| const Reference< XTransferable >& aXTransferable, CFormatEtcContainer& aFormatEtcContainer ) |
| { |
| Sequence< DataFlavor > aFlavorList = aXTransferable->getTransferDataFlavors( ); |
| sal_Int32 nFlavors = aFlavorList.getLength( ); |
| sal_Bool bUnicodeRegistered = sal_False; |
| DataFlavor aFlavor; |
| |
| for( sal_Int32 i = 0; i < nFlavors; i++ ) |
| { |
| aFlavor = aFlavorList[i]; |
| CFormatEtc fetc = m_DataFormatTranslator.getFormatEtcFromDataFlavor( aFlavor ); |
| |
| // maybe an internal format so we ignore it |
| if ( CF_INVALID == fetc.getClipformat( ) ) |
| continue; |
| |
| if ( !needsToSynthesizeAccompanyFormats( fetc ) ) |
| aFormatEtcContainer.addFormatEtc( fetc ); |
| else |
| { |
| // if we haven't registered any text format up to now |
| if ( m_DataFormatTranslator.isTextFormat( fetc.getClipformat() ) && !bUnicodeRegistered ) |
| { |
| // if the transferable supports unicode text we ignore |
| // any further text format the transferable offers |
| // because we can create it from Unicode text in addition |
| // we register CF_TEXT for non unicode clients |
| if ( m_DataFormatTranslator.isUnicodeTextFormat( fetc.getClipformat() ) ) |
| { |
| aFormatEtcContainer.addFormatEtc( fetc ); // add CF_UNICODE |
| aFormatEtcContainer.addFormatEtc( |
| m_DataFormatTranslator.getFormatEtcForClipformat( CF_TEXT ) ); // add CF_TEXT |
| bUnicodeRegistered = sal_True; |
| } |
| else if ( !hasUnicodeFlavor( aXTransferable ) ) |
| { |
| // we try to investigate the charset and make a valid |
| // windows codepage from this charset the default |
| // return value is the result of GetACP( ) |
| OUString charset = getCharsetFromDataFlavor( aFlavor ); |
| sal_uInt32 txtCP = getWinCPFromMimeCharset( charset ); |
| |
| // we try to get a Locale appropriate for this codepage |
| if ( findLocaleForTextCodePage( ) ) |
| { |
| m_TxtCodePage = txtCP; |
| |
| aFormatEtcContainer.addFormatEtc( |
| m_DataFormatTranslator.getFormatEtcForClipformat( CF_UNICODETEXT ) ); |
| |
| if ( !IsOEMCP( m_TxtCodePage ) ) |
| aFormatEtcContainer.addFormatEtc( |
| m_DataFormatTranslator.getFormatEtcForClipformat( CF_TEXT ) ); |
| else |
| aFormatEtcContainer.addFormatEtc( |
| m_DataFormatTranslator.getFormatEtcForClipformat( CF_OEMTEXT ) ); |
| |
| aFormatEtcContainer.addFormatEtc( |
| m_DataFormatTranslator.getFormatEtcForClipformat( CF_LOCALE ) ); |
| |
| // we save the flavor so it's easier when |
| // queried for it in XTDataObject::GetData(...) |
| m_RegisteredTextFlavor = aFlavor; |
| m_bHasSynthesizedLocale = sal_True; |
| } |
| } |
| } |
| else if ( m_DataFormatTranslator.isTextHtmlFormat( fetc.getClipformat( ) ) ) // Html (Hyper Text...) |
| { |
| // we add text/html ( HTML (HyperText Markup Language) ) |
| aFormatEtcContainer.addFormatEtc( fetc ); |
| |
| // and HTML Format |
| OUString htmlFormat( OUString::createFromAscii( "HTML Format" ) ); |
| aFormatEtcContainer.addFormatEtc( |
| m_DataFormatTranslator.getFormatEtcForClipformatName( htmlFormat ) ); |
| } |
| } |
| } |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| sal_Bool SAL_CALL CFormatRegistrar::hasSynthesizedLocale( ) const |
| { |
| return m_bHasSynthesizedLocale; |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| LCID SAL_CALL CFormatRegistrar::getSynthesizedLocale( ) const |
| { |
| return m_TxtLocale; |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| sal_uInt32 SAL_CALL CFormatRegistrar::getRegisteredTextCodePage( ) const |
| { |
| return m_TxtCodePage; |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| DataFlavor SAL_CALL CFormatRegistrar::getRegisteredTextFlavor( ) const |
| { |
| return m_RegisteredTextFlavor; |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| sal_Bool SAL_CALL CFormatRegistrar::isSynthesizeableFormat( const CFormatEtc& aFormatEtc ) const |
| { |
| return ( m_DataFormatTranslator.isOemOrAnsiTextFormat( aFormatEtc.getClipformat() ) || |
| m_DataFormatTranslator.isUnicodeTextFormat( aFormatEtc.getClipformat() ) || |
| m_DataFormatTranslator.isHTMLFormat( aFormatEtc.getClipformat() ) ); |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| inline |
| sal_Bool SAL_CALL CFormatRegistrar::needsToSynthesizeAccompanyFormats( const CFormatEtc& aFormatEtc ) const |
| { |
| return ( m_DataFormatTranslator.isOemOrAnsiTextFormat( aFormatEtc.getClipformat() ) || |
| m_DataFormatTranslator.isUnicodeTextFormat( aFormatEtc.getClipformat() ) || |
| m_DataFormatTranslator.isTextHtmlFormat( aFormatEtc.getClipformat( ) ) ); |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| OUString SAL_CALL CFormatRegistrar::getCharsetFromDataFlavor( const DataFlavor& aFlavor ) |
| { |
| OUString charset; |
| |
| try |
| { |
| Reference< XMimeContentTypeFactory > xMimeFac( |
| m_SrvMgr->createInstance( OUString::createFromAscii( \ |
| "com.sun.star.datatransfer.MimeContentTypeFactory" ) ), UNO_QUERY ); |
| |
| if( xMimeFac.is( ) ) |
| { |
| Reference< XMimeContentType > xMimeType( xMimeFac->createMimeContentType( aFlavor.MimeType ) ); |
| if ( xMimeType->hasParameter( TEXTPLAIN_PARAM_CHARSET ) ) |
| charset = xMimeType->getParameterValue( TEXTPLAIN_PARAM_CHARSET ); |
| else |
| charset = getMimeCharsetFromWinCP( GetACP( ), PRE_WINDOWS_CODEPAGE ); |
| } |
| } |
| catch(NoSuchElementException&) |
| { |
| OSL_ENSURE( sal_False, "Unexpected" ); |
| } |
| catch(...) |
| { |
| OSL_ENSURE( sal_False, "Invalid data flavor" ); |
| } |
| |
| return charset; |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| sal_Bool SAL_CALL CFormatRegistrar::hasUnicodeFlavor( const Reference< XTransferable >& aXTransferable ) const |
| { |
| CFormatEtc fetc( CF_UNICODETEXT ); |
| |
| DataFlavor aFlavor = |
| m_DataFormatTranslator.getDataFlavorFromFormatEtc( fetc ); |
| |
| return aXTransferable->isDataFlavorSupported( aFlavor ); |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| inline |
| sal_Bool CFormatRegistrar::isEqualCurrentSystemCodePage( sal_uInt32 aCodePage ) const |
| { |
| return ( (aCodePage == GetOEMCP()) || (aCodePage == GetACP()) ); |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| sal_Bool SAL_CALL CFormatRegistrar::findLocaleForTextCodePage( ) |
| { |
| m_TxtLocale = 0; |
| EnumSystemLocalesA( CFormatRegistrar::EnumLocalesProc, LCID_INSTALLED ); |
| return ( IsValidLocale( m_TxtLocale, LCID_INSTALLED ) ) ? sal_True : sal_False; |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| sal_Bool SAL_CALL CFormatRegistrar::isLocaleCodePage( LCID lcid, LCTYPE lctype, sal_uInt32 codepage ) |
| { |
| char buff[6]; |
| sal_uInt32 localeCodePage; |
| |
| OSL_ASSERT( IsValidLocale( lcid, LCID_INSTALLED ) ); |
| |
| // get the ansi codepage of the current locale |
| GetLocaleInfoA( lcid, lctype, buff, sizeof( buff ) ); |
| localeCodePage = atol( buff ); |
| |
| return ( localeCodePage == codepage ); |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| inline |
| sal_Bool SAL_CALL CFormatRegistrar::isLocaleOemCodePage( LCID lcid, sal_uInt32 codepage ) |
| { |
| return isLocaleCodePage( lcid, LOCALE_IDEFAULTCODEPAGE, codepage ); |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| inline |
| sal_Bool SAL_CALL CFormatRegistrar::isLocaleAnsiCodePage( LCID lcid, sal_uInt32 codepage ) |
| { |
| return isLocaleCodePage( lcid, LOCALE_IDEFAULTANSICODEPAGE, codepage ); |
| } |
| |
| //------------------------------------------------------------------------ |
| // |
| //------------------------------------------------------------------------ |
| |
| BOOL CALLBACK CFormatRegistrar::EnumLocalesProc( LPSTR lpLocaleStr ) |
| { |
| // the lpLocaleStr parametere is hexadecimal |
| LCID lcid = strtol( lpLocaleStr, NULL, 16 ); |
| |
| if ( isLocaleAnsiCodePage( lcid, CFormatRegistrar::m_TxtCodePage ) || |
| isLocaleOemCodePage( lcid, CFormatRegistrar::m_TxtCodePage ) ) |
| { |
| CFormatRegistrar::m_TxtLocale = lcid; |
| return sal_False; // stop enumerating |
| } |
| |
| return sal_True; |
| } |
| |