#95912# #i2345# support more type conversions

This commit is contained in:
Philipp Lohmann 2001-12-12 18:05:41 +00:00
parent 33994b0c80
commit 7e3ddd934d
2 changed files with 118 additions and 65 deletions

View file

@ -2,9 +2,9 @@
*
* $RCSfile: X11_selection.cxx,v $
*
* $Revision: 1.43 $
* $Revision: 1.44 $
*
* last change: $Author: pl $ $Date: 2001-12-11 20:19:13 $
* last change: $Author: pl $ $Date: 2001-12-12 19:05:41 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@ -134,7 +134,6 @@ static const int nXdndProtocolRevision = 4;
// and X convention types
// for clipboard and primary selections there is only a convention for text
// that the encoding name of the text is taken as type in all capitalized letters
// TODO: implement Compound Text conversion
// the convention for Xdnd is mime types as specified by the corresponding
// RFC's with the addition that text/plain without charset tag contains iso8859-1
struct NativeTypeEntry
@ -155,6 +154,7 @@ static NativeTypeEntry aNativeConversionTab[] =
{ 0, "text/plain;charset=utf-16", "ISO10646-1", 16 },
{ 0, "text/plain;charset=utf-8", "UTF8_STRING", 8 },
{ 0, "text/plain;charset=utf-8", "UTF-8", 8 },
{ 0, "text/plain;charset=utf-8", "text/plain;charset=UTF-8", 8 },
// ISO encodings
{ 0, "text/plain;charset=iso8859-2", "ISO8859-2", 8 },
{ 0, "text/plain;charset=iso8859-3", "ISO8859-3", 8 },
@ -202,9 +202,9 @@ rtl_TextEncoding x11::getTextPlainEncoding( const OUString& rMimeType )
{
OString aEncToken = OUStringToOString( aToken.getToken( 0, '=', nPos ), RTL_TEXTENCODING_ISO_8859_1 );
aEncoding = rtl_getTextEncodingFromUnixCharset( aEncToken.getStr() );
if( aEncToken == RTL_TEXTENCODING_DONTKNOW )
if( aEncoding == RTL_TEXTENCODING_DONTKNOW )
{
if( aEncToken.equals( "utf-8" ) )
if( aEncToken.equalsIgnoreAsciiCase( "utf-8" ) )
aEncoding = RTL_TEXTENCODING_UTF8;
}
if( aEncoding != RTL_TEXTENCODING_DONTKNOW )
@ -213,6 +213,10 @@ rtl_TextEncoding x11::getTextPlainEncoding( const OUString& rMimeType )
}
}
}
#ifdef DEBUG
if( aEncoding == RTL_TEXTENCODING_DONTKNOW )
fprintf( stderr, "getTextPlainEncoding( %s ) failed\n", OUStringToOString( rMimeType, RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
#endif
return aEncoding;
}
@ -379,7 +383,7 @@ void SelectionManager::initialize( const Sequence< Any >& arguments ) throw (::c
m_nINCRAtom = getAtom( OUString::createFromAscii( "INCR" ) );
m_nCOMPOUNDAtom = getAtom( OUString::createFromAscii( "COMPOUND_TEXT" ) );
m_nUTF16Atom = getAtom( OUString::createFromAscii( "ISO10646-1" ) );
m_nUTF8Atom = getAtom( OUString::createFromAscii( "UTF8_STRING" ) );
// m_nUTF16Atom = getAtom( OUString::createFromAscii( "text/plain;charset=ISO-10646-UCS-2" ) );
// Atoms for Xdnd protocol
m_nXdndAware = getAtom( OUString::createFromAscii( "XdndAware" ) );
@ -746,7 +750,7 @@ bool SelectionManager::requestOwnership( Atom selection )
// ------------------------------------------------------------------------
Atom SelectionManager::convertTypeToNative( const OUString& rType, Atom selection, int& rFormat )
void SelectionManager::convertTypeToNative( const OUString& rType, Atom selection, int& rFormat, ::std::list< Atom >& rConversions )
{
NativeTypeEntry* pTab = selection == m_nXdndSelection ? aXdndConversionTab : aNativeConversionTab;
int nTabEntries = selection == m_nXdndSelection
@ -754,6 +758,7 @@ Atom SelectionManager::convertTypeToNative( const OUString& rType, Atom selectio
sizeof(aNativeConversionTab)/sizeof(aNativeConversionTab[0]);
OString aType( OUStringToOString( rType, RTL_TEXTENCODING_ISO_8859_1 ) );
rFormat = 0;
for( int i = 0; i < nTabEntries; i++ )
{
if( aType.equalsIgnoreAsciiCase( pTab[i].pType ) )
@ -761,11 +766,12 @@ Atom SelectionManager::convertTypeToNative( const OUString& rType, Atom selectio
if( ! pTab[i].nAtom )
pTab[i].nAtom = getAtom( OStringToOUString( pTab[i].pNativeType, RTL_TEXTENCODING_ISO_8859_1 ) );
rFormat = pTab[i].nFormat;
return pTab[i].nAtom;
rConversions.push_back( pTab[i].nAtom );
}
}
rFormat = 8; // byte buffer
return getAtom( rType );
if( ! rFormat )
rFormat = 8; // byte buffer
rConversions.push_back( getAtom( rType ) );
};
// ------------------------------------------------------------------------
@ -851,20 +857,22 @@ bool SelectionManager::getPasteData( Atom selection, const ::rtl::OUString& rTyp
int nFormat;
bool bSuccess = false;
::std::hash_map< Atom, Selection* >::iterator it;
{
MutexGuard aGuard(m_aMutex);
it = m_aSelections.find( selection );
if( it == m_aSelections.end() )
return false;
}
const Sequence< DataFlavor >& rTypes( it->second->m_aTypes );
const Sequence< Atom >& rNativeTypes( it->second->m_aNativeTypes );
if( rType.equalsAsciiL( "text/plain;charset=utf-16", 25 ) )
{
// lets see if we have UTF16 else try to find something convertible
::std::hash_map< Atom, Selection* >::iterator it;
{
MutexGuard aGuard(m_aMutex);
it = m_aSelections.find( selection );
if( it == m_aSelections.end() )
return false;
}
if( it->second->m_aTypes.getLength() && ! it->second->m_bHaveUTF16 )
{
const Sequence< DataFlavor >& rTypes( it->second->m_aTypes );
Sequence< sal_Int8 > aData;
if( it->second->m_bHaveCompound &&
getPasteData( selection,
@ -883,12 +891,9 @@ bool SelectionManager::getPasteData( Atom selection, const ::rtl::OUString& rTyp
rtl_TextEncoding aEncoding = getTextPlainEncoding( rTypes.getConstArray()[i].MimeType );
if( aEncoding != RTL_TEXTENCODING_DONTKNOW &&
aEncoding != RTL_TEXTENCODING_UNICODE &&
getPasteData(
selection,
convertTypeToNative(
rTypes.getConstArray()[i].MimeType,
selection, nFormat ),
aData )
getPasteData( selection,
rNativeTypes.getConstArray()[i],
aData )
)
{
#ifdef DEBUG
@ -908,7 +913,21 @@ bool SelectionManager::getPasteData( Atom selection, const ::rtl::OUString& rTyp
}
}
if( ! bSuccess )
bSuccess = getPasteData( selection, convertTypeToNative( rType, selection, nFormat ), rData );
{
::std::list< Atom > aTypes;
convertTypeToNative( rType, selection, nFormat, aTypes );
::std::list< Atom >::const_iterator type_it;
Atom nSelectedType = None;
const Atom* pNativeTypes = rNativeTypes.getConstArray();
for( type_it = aTypes.begin(); type_it != aTypes.end() && nSelectedType == None; ++type_it )
{
for( int i = 0; i < rNativeTypes.getLength() && nSelectedType == None; i++ )
if( pNativeTypes[i] == *type_it )
nSelectedType = *type_it;
}
if( nSelectedType != None )
bSuccess = getPasteData( selection, nSelectedType, rData );
}
#ifdef DEBUG
fprintf( stderr, "getPasteData for selection %s and data type %s returns %s, returned sequence has length %d\n",
OUStringToOString( getString( selection ), RTL_TEXTENCODING_ISO_8859_1 ).getStr(),
@ -1014,12 +1033,15 @@ bool SelectionManager::getPasteDataTypes( Atom selection, Sequence< DataFlavor >
else if( ! getPasteData( selection, m_nTARGETSAtom, aAtoms ) )
aAtoms = Sequence< sal_Int8 >();
Sequence< Atom > aNativeTypes;
if( aAtoms.getLength() )
{
int nAtoms = aAtoms.getLength() / 4;
Atom* pAtoms = (Atom*)aAtoms.getArray();
rTypes.realloc( nAtoms );
aNativeTypes.realloc( nAtoms );
DataFlavor* pFlavors = rTypes.getArray();
Atom* pNativeTypes = aNativeTypes.getArray();
while( nAtoms-- )
{
if( *pAtoms == m_nCOMPOUNDAtom )
@ -1040,6 +1062,7 @@ bool SelectionManager::getPasteDataTypes( Atom selection, Sequence< DataFlavor >
}
}
pFlavors++;
*pNativeTypes++ = *pAtoms;
}
pAtoms++;
}
@ -1053,6 +1076,11 @@ bool SelectionManager::getPasteDataTypes( Atom selection, Sequence< DataFlavor >
aTemp.getArray()[0].MimeType = OUString::createFromAscii( "text/plain;charset=utf-16" );
aTemp.getArray()[0].DataType = getCppuType( (OUString*)0 );
rTypes = aTemp;
Sequence< Atom > aNativeTemp( nNewFlavors );
memcpy( aNativeTemp.getArray()+1, aNativeTypes.getConstArray(), sizeof(Atom)*(nNewFlavors-1) );
aNativeTemp.getArray()[0] = None;
aNativeTypes = aNativeTemp;
}
}
@ -1065,6 +1093,7 @@ bool SelectionManager::getPasteDataTypes( Atom selection, Sequence< DataFlavor >
if( bSuccess )
{
it->second->m_aTypes = rTypes;
it->second->m_aNativeTypes = aNativeTypes;
it->second->m_nLastTimestamp = time( NULL );
it->second->m_bHaveUTF16 = bHaveUTF16;
it->second->m_bHaveCompound = bHaveCompound;
@ -1072,6 +1101,7 @@ bool SelectionManager::getPasteDataTypes( Atom selection, Sequence< DataFlavor >
else
{
it->second->m_aTypes = Sequence< DataFlavor >();
it->second->m_aNativeTypes = Sequence< Atom >();
it->second->m_nLastTimestamp = 0;
it->second->m_bHaveUTF16 = false;
it->second->m_bHaveCompound = false;
@ -1128,24 +1158,35 @@ void SelectionManager::handleSelectionRequest( XSelectionRequestEvent& rRequest
aGuard.clear();
Sequence< DataFlavor > aFlavors = xTrans->getTransferDataFlavors();
aGuard.reset();
Atom* pTypes = (Atom*)alloca( aFlavors.getLength()+2 * sizeof( Atom ) );
int nFormat;
::std::list< Atom > aConversions;
int i, nFormat;
int nFlavors = aFlavors.getLength();
for( i = 0; i < nFlavors; i++ )
convertTypeToNative( aFlavors.getConstArray()[i].MimeType, rRequest.selection, nFormat, aConversions );
bool bHaveUTF16 = false;
int nTypes = aFlavors.getLength();
for( int i = 0; i < nTypes; i++ )
{
pTypes[i] = convertTypeToNative( aFlavors.getConstArray()[i].MimeType, rRequest.selection, nFormat );
if( pTypes[i] == m_nUTF16Atom )
::std::list< Atom >::const_iterator it;
for( it = aConversions.begin(); it != aConversions.end() && ! bHaveUTF16; ++it )
if( *it == m_nUTF16Atom )
bHaveUTF16 = true;
}
if( bHaveUTF16 )
{
pTypes[ nTypes++ ] = m_nUTF8Atom;
pTypes[ nTypes++ ] = m_nCOMPOUNDAtom;
convertTypeToNative( OUString::createFromAscii( "text/plain;charset=utf-8" ), rRequest.selection, nFormat, aConversions );
aConversions.push_back( m_nCOMPOUNDAtom );
}
int nTypes = aConversions.size();
Atom* pTypes = (Atom*)alloca( nTypes * sizeof( Atom ) );
for( i = 0, it = aConversions.begin(); i < nTypes; i++, ++it )
pTypes[i] = *it;
XChangeProperty( m_pDisplay, rRequest.requestor, rRequest.property,
XA_ATOM, 32, PropModeReplace, (const unsigned char*)pTypes, nTypes );
aNotify.xselection.property = rRequest.property;
#ifdef DEBUG
fprintf( stderr, "sending type list:\n" );
for( int k = 0; k < nTypes; k++ )
fprintf( stderr, " %s\n", pTypes[k] ? XGetAtomName( m_pDisplay, pTypes[k] ) : "<None>" );
#endif
}
}
else
@ -2347,13 +2388,15 @@ void SelectionManager::updateDragWindow( int nX, int nY, Window aRoot )
aEvent.xclient.data.l[1] = m_nCurrentProtocolVersion << 24;
memset( aEvent.xclient.data.l + 2, 0, sizeof( long )*3 );
// fill in data types
if( m_aDragFlavors.getLength() > 3 )
aEvent.xclient.data.l[1] |= 1;
int format;
for( int i = 0; i < m_aDragFlavors.getLength() && i < 3; i++ )
{
aEvent.xclient.data.l[i+2] = convertTypeToNative( m_aDragFlavors.getConstArray()[i].MimeType, m_nXdndSelection, format );
}
::std::list< Atom > aConversions;
for( int nFlavor = 0; nFlavor < m_aDragFlavors.getLength(); nFlavor++ )
convertTypeToNative( m_aDragFlavors.getConstArray()[nFlavor].MimeType, m_nXdndSelection, format, aConversions );
if( aConversions.size() > 3 )
aEvent.xclient.data.l[1] |= 1;
::std::list< Atom >::const_iterator type_it = aConversions.begin();
for( int i = 0; type_it != aConversions.end() && i < 3; i++, ++type_it )
aEvent.xclient.data.l[i+2] = *type_it;
XSendEvent( m_pDisplay, m_aDropProxy, False, NoEventMask, &aEvent );
}
}
@ -2480,14 +2523,19 @@ void SelectionManager::startDrag(
requestOwnership( m_nXdndSelection );
Atom* pTypes = new Atom[m_aDragFlavors.getLength()];
::std::list< Atom > aConversions;
::std::list< Atom >::const_iterator type_it;
int format;
for( int i = 0; i < m_aDragFlavors.getLength(); i++ )
{
pTypes[i] = convertTypeToNative( m_aDragFlavors.getConstArray()[i].MimeType, m_nXdndSelection, format );
}
XChangeProperty( m_pDisplay, m_aWindow, m_nXdndTypeList, XA_ATOM, 32, PropModeReplace, (unsigned char*)pTypes, m_aDragFlavors.getLength() );
delete pTypes;
convertTypeToNative( m_aDragFlavors.getConstArray()[i].MimeType, m_nXdndSelection, format, aConversions );
int nTypes = aConversions.size();
Atom* pTypes = (Atom*)alloca( sizeof(Atom)*nTypes );
type_it = aConversions.begin();
for( int n = 0; n < nTypes; n++, ++type_it )
pTypes[n] = *type_it;
XChangeProperty( m_pDisplay, m_aWindow, m_nXdndTypeList, XA_ATOM, 32, PropModeReplace, (unsigned char*)pTypes, nTypes );
m_nSourceActions = sourceActions | DNDConstants::ACTION_DEFAULT;
m_nUserDragAction = DNDConstants::ACTION_MOVE & m_nSourceActions;
@ -2668,15 +2716,18 @@ void SelectionManager::transferablesFlavorsChanged()
MutexGuard aGuard(m_aMutex);
m_aDragFlavors = m_xDragSourceTransferable->getTransferDataFlavors();
int format, i;
Atom* pTypes = new Atom[m_aDragFlavors.getLength()];
int format;
for( int i = 0; i < m_aDragFlavors.getLength(); i++ )
{
pTypes[i] = convertTypeToNative( m_aDragFlavors.getConstArray()[i].MimeType, m_nXdndSelection, format );
}
XChangeProperty( m_pDisplay, m_aWindow, m_nXdndTypeList, XA_ATOM, 32, PropModeReplace, (unsigned char*)pTypes, m_aDragFlavors.getLength() );
delete pTypes;
::std::list< Atom > aConversions;
::std::list< Atom >::const_iterator type_it;
for( i = 0; i < m_aDragFlavors.getLength(); i++ )
convertTypeToNative( m_aDragFlavors.getConstArray()[i].MimeType, m_nXdndSelection, format, aConversions );
int nTypes = aConversions.size();
Atom* pTypes = (Atom*)alloca( sizeof(Atom)*aConversions.size() );
for( i = 0, type_it = aConversions.begin(); type_it != aConversions.end(); ++type_it, i++ )
pTypes[i] = *type_it;
XChangeProperty( m_pDisplay, m_aWindow, m_nXdndTypeList, XA_ATOM, 32, PropModeReplace, (unsigned char*)pTypes, nTypes );
if( m_aCurrentDropWindow != None && m_nCurrentProtocolVersion >= 0 )
{
@ -2698,12 +2749,11 @@ void SelectionManager::transferablesFlavorsChanged()
aEvent.xclient.data.l[1] = m_nCurrentProtocolVersion << 24;
memset( aEvent.xclient.data.l + 2, 0, sizeof( long )*3 );
// fill in data types
if( m_aDragFlavors.getLength() > 3 )
if( nTypes > 3 )
aEvent.xclient.data.l[1] |= 1;
for( int i = 0; i < m_aDragFlavors.getLength() && i < 3; i++ )
{
aEvent.xclient.data.l[i+2] = convertTypeToNative( m_aDragFlavors.getConstArray()[i].MimeType, m_nXdndSelection, format );
}
for( int i = 0; i < nTypes && i < 3; i++ )
aEvent.xclient.data.l[i+2] = pTypes[i];
XSendEvent( m_pDisplay, m_aDropProxy, False, NoEventMask, &aEvent );
}
}

View file

@ -2,9 +2,9 @@
*
* $RCSfile: X11_selection.hxx,v $
*
* $Revision: 1.15 $
* $Revision: 1.16 $
*
* last change: $Author: pl $ $Date: 2001-11-26 14:14:30 $
* last change: $Author: pl $ $Date: 2001-12-12 19:05:41 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@ -255,8 +255,10 @@ namespace x11 {
m_aData;
Sequence< ::com::sun::star::datatransfer::DataFlavor >
m_aTypes;
Sequence< Atom > m_aNativeTypes;
// this is used for caching
// m_aTypes is invalid after 2 seconds
// m_aNativeTypes contains the corresponding original atom
int m_nLastTimestamp;
bool m_bHaveUTF16;
bool m_bHaveCompound;
@ -376,7 +378,6 @@ namespace x11 {
Atom m_nINCRAtom;
Atom m_nCOMPOUNDAtom;
Atom m_nUTF16Atom;
Atom m_nUTF8Atom;
Atom m_nXdndAware;
Atom m_nXdndEnter;
Atom m_nXdndLeave;
@ -468,7 +469,9 @@ namespace x11 {
const ::rtl::OUString& getString( Atom nAtom );
// type conversion
Atom convertTypeToNative( const ::rtl::OUString& rType, Atom selection, int& rFormat );
// note: convertTypeToNative does NOT clear the list, so you can append
// multiple types to the same list
void convertTypeToNative( const ::rtl::OUString& rType, Atom selection, int& rFormat, ::std::list< Atom >& rConversions );
::rtl::OUString convertTypeFromNative( Atom nType, Atom selection, int& rFormat );
// methods for transferable