1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: DataFlavorMapping.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #include "vcl/unohelp.hxx"
32 #include <DataFlavorMapping.hxx>
33 #include "HtmlFmtFlt.hxx"
34 #include "PictToBmpFlt.hxx"
35 #include "com/sun/star/datatransfer/UnsupportedFlavorException.hpp"
36 #include "com/sun/star/datatransfer/XMimeContentType.hpp"
37 #include "com/sun/star/lang/XMultiServiceFactory.hpp"
38 #include "com/sun/star/uno/Sequence.hxx"
40 #include <rtl/ustring.hxx>
41 #include <rtl/memory.h>
42 #include <osl/endian.h>
48 #include <QuickTime/QuickTime.h>
51 using namespace ::com::sun::star::datatransfer
;
53 using namespace ::com::sun::star::uno
;
54 using namespace com::sun::star::lang
;
60 const Type CPPUTYPE_SEQINT8
= getCppuType((Sequence
<sal_Int8
>*)0);
61 const Type CPPUTYPE_OUSTRING
= getCppuType( (OUString
*)0 );
63 /* Determine whether or not a DataFlavor is valid.
65 bool isValidFlavor(const DataFlavor
& aFlavor
)
67 size_t len
= aFlavor
.MimeType
.getLength();
68 Type dtype
= aFlavor
.DataType
;
69 return ((len
> 0) && ((dtype
== CPPUTYPE_SEQINT8
) || (dtype
== CPPUTYPE_OUSTRING
)));
72 typedef vector
<sal_Unicode
> UnicodeBuffer
;
74 OUString
NSStringToOUString(NSString
* cfString
)
76 BOOST_ASSERT(cfString
&& "Invalid parameter");
78 const char* utf8Str
= [cfString UTF8String
];
79 unsigned int len
= rtl_str_getLength(utf8Str
);
81 return OUString(utf8Str
, len
, RTL_TEXTENCODING_UTF8
);
84 NSString
* OUStringToNSString(const OUString
& ustring
)
86 OString utf8Str
= OUStringToOString(ustring
, RTL_TEXTENCODING_UTF8
);
87 return [NSString stringWithCString
: utf8Str
.getStr() encoding
: NSUTF8StringEncoding
];
91 const NSString
* PBTYPE_UT16
= @
"CorePasteboardFlavorType 0x75743136";
92 const NSString
* PBTYPE_PICT
= @
"CorePasteboardFlavorType 0x50494354";
93 const NSString
* PBTYPE_HTML
= @
"CorePasteboardFlavorType 0x48544D4C";
94 const NSString
* PBTYPE_SODX
= @
"application/x-openoffice-objectdescriptor-xml;windows_formatname=\"Star Object Descriptor (XML)\"";
95 const NSString
* PBTYPE_SESX
= @
"application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\"";
96 const NSString
* PBTYPE_SLSDX
= @
"application/x-openoffice-linksrcdescriptor-xml;windows_formatname=\"Star Link Source Descriptor (XML)\"";
97 const NSString
* PBTYPE_ESX
= @
"application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\"";
98 const NSString
* PBTYPE_LSX
= @
"application/x-openoffice-link-source-xml;windows_formatname=\"Star Link Source (XML)\"";
99 const NSString
* PBTYPE_EOX
= @
"application/x-openoffice-embedded-obj-xml;windows_formatname=\"Star Embedded Object (XML)\"";
100 const NSString
* PBTYPE_SVXB
= @
"application/x-openoffice-svbx;windows_formatname=\"SVXB (StarView Bitmap/Animation)\"";
101 const NSString
* PBTYPE_GDIMF
= @
"application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"";
102 const NSString
* PBTYPE_WMF
= @
"application/x-openoffice-wmf;windows_formatname=\"Image WMF\"";
103 const NSString
* PBTYPE_EMF
= @
"application/x-openoffice-emf;windows_formatname=\"Image EMF\"";
105 const NSString
* PBTYPE_DUMMY_INTERNAL
= @
"application/x-openoffice-internal";
107 const char* FLAVOR_SODX
= "application/x-openoffice-objectdescriptor-xml;windows_formatname=\"Star Object Descriptor (XML)\"";
108 const char* FLAVOR_SESX
= "application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\"";
109 const char* FLAVOR_SLSDX
= "application/x-openoffice-linksrcdescriptor-xml;windows_formatname=\"Star Link Source Descriptor (XML)\"";
110 const char* FLAVOR_ESX
= "application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\"";
111 const char* FLAVOR_LSX
= "application/x-openoffice-link-source-xml;windows_formatname=\"Star Link Source (XML)\"";
112 const char* FLAVOR_EOX
= "application/x-openoffice-embedded-obj-xml;windows_formatname=\"Star Embedded Object (XML)\"";
113 const char* FLAVOR_SVXB
= "application/x-openoffice-svbx;windows_formatname=\"SVXB (StarView Bitmap/Animation)\"";
114 const char* FLAVOR_GDIMF
= "application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"";
115 const char* FLAVOR_WMF
= "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"";
116 const char* FLAVOR_EMF
= "application/x-openoffice-emf;windows_formatname=\"Image EMF\"";
118 const char* FLAVOR_DUMMY_INTERNAL
= "application/x-openoffice-internal";
123 NSString
* SystemFlavor
;
124 const char* OOoFlavor
;
125 const char* HumanPresentableName
;
129 /* At the moment it appears as if only MS Office pastes "public.html" to the clipboard.
131 FlavorMap flavorMap
[] =
133 { NSStringPboardType
, "text/plain;charset=utf-16", "Unicode Text (UTF-16)", CPPUTYPE_OUSTRING
},
134 { NSRTFPboardType
, "text/richtext", "Rich Text Format", CPPUTYPE_SEQINT8
},
135 { NSPICTPboardType
, "image/bmp", "Windows Bitmap", CPPUTYPE_SEQINT8
},
136 { NSHTMLPboardType
, "text/html", "Plain Html", CPPUTYPE_SEQINT8
},
137 { NSFilenamesPboardType
, "application/x-openoffice-filelist;windows_formatname=\"FileList\"", "FileList", CPPUTYPE_SEQINT8
},
138 { PBTYPE_SESX
, FLAVOR_SESX
, "Star Embed Source (XML)", CPPUTYPE_SEQINT8
},
139 { PBTYPE_SLSDX
, FLAVOR_SLSDX
, "Star Link Source Descriptor (XML)", CPPUTYPE_SEQINT8
},
140 { PBTYPE_ESX
, FLAVOR_ESX
, "Star Embed Source (XML)", CPPUTYPE_SEQINT8
},
141 { PBTYPE_LSX
, FLAVOR_LSX
, "Star Link Source (XML)", CPPUTYPE_SEQINT8
},
142 { PBTYPE_EOX
, FLAVOR_EOX
, "Star Embedded Object (XML)", CPPUTYPE_SEQINT8
},
143 { PBTYPE_SVXB
, FLAVOR_SVXB
, "SVXB (StarView Bitmap/Animation", CPPUTYPE_SEQINT8
},
144 { PBTYPE_GDIMF
, FLAVOR_GDIMF
, "GDIMetaFile", CPPUTYPE_SEQINT8
},
145 { PBTYPE_WMF
, FLAVOR_WMF
, "Windows MetaFile", CPPUTYPE_SEQINT8
},
146 { PBTYPE_EMF
, FLAVOR_EMF
, "Windows Enhanced MetaFile", CPPUTYPE_SEQINT8
},
147 { PBTYPE_SODX
, FLAVOR_SODX
, "Star Object Descriptor (XML)", CPPUTYPE_SEQINT8
},
148 { PBTYPE_DUMMY_INTERNAL
, FLAVOR_DUMMY_INTERNAL
, "internal data",CPPUTYPE_SEQINT8
}
149 // { PBTYPE_UT16, "text/plain;charset=utf-16", "Unicode Text (UTF-16)", CPPUTYPE_OUSTRING }
150 // { kUTTypePICT, @"PICT", "image/x-macpict;windows_formatname=\"Mac Pict\"", "Mac Pict", CPPUTYPE_SEQINT8 }
151 // { kUTTypeHTML, @"HTML", "text/html", "Plain Html", CPPUTYPE_SEQINT8 }
155 #define SIZE_FLAVOR_MAP (sizeof(flavorMap)/sizeof(FlavorMap))
158 inline bool isByteSequenceType(const Type
& theType
)
160 return (theType
== CPPUTYPE_SEQINT8
);
163 inline bool isOUStringType(const Type
& theType
)
165 return (theType
== CPPUTYPE_OUSTRING
);
168 } // namespace private
171 //###########################
173 /* A base class for other data provider.
175 class DataProviderBaseImpl
: public DataProvider
178 DataProviderBaseImpl(const Any
& data
);
179 DataProviderBaseImpl(id data
);
180 virtual ~DataProviderBaseImpl();
184 //NSData* mSystemData;
188 DataProviderBaseImpl::DataProviderBaseImpl(const Any
& data
) :
194 DataProviderBaseImpl::DataProviderBaseImpl(id data
) :
197 [mSystemData retain
];
201 DataProviderBaseImpl::~DataProviderBaseImpl()
205 [mSystemData release
];
209 //#################################
211 class UniDataProvider
: public DataProviderBaseImpl
214 UniDataProvider(const Any
& data
);
216 UniDataProvider(NSData
* data
);
218 virtual NSData
* getSystemData();
220 virtual Any
getOOoData();
223 UniDataProvider::UniDataProvider(const Any
& data
) :
224 DataProviderBaseImpl(data
)
228 UniDataProvider::UniDataProvider(NSData
* data
) :
229 DataProviderBaseImpl(data
)
233 NSData
* UniDataProvider::getSystemData()
239 ustr
.convertToString(&strUtf8
, RTL_TEXTENCODING_UTF8
, OUSTRING_TO_OSTRING_CVTFLAGS
);
241 return [NSData dataWithBytes
: strUtf8
.getStr() length
: strUtf8
.getLength()];
244 Any
UniDataProvider::getOOoData()
250 oOOData
= makeAny(OUString(reinterpret_cast<const sal_Char
*>([mSystemData bytes
]),
251 [mSystemData length
],
252 RTL_TEXTENCODING_UTF8
));
262 //###########################
264 class ByteSequenceDataProvider
: public DataProviderBaseImpl
267 ByteSequenceDataProvider(const Any
& data
);
269 ByteSequenceDataProvider(NSData
* data
);
271 virtual NSData
* getSystemData();
273 virtual Any
getOOoData();
276 ByteSequenceDataProvider::ByteSequenceDataProvider(const Any
& data
) :
277 DataProviderBaseImpl(data
)
281 ByteSequenceDataProvider::ByteSequenceDataProvider(NSData
* data
) :
282 DataProviderBaseImpl(data
)
287 NSData
* ByteSequenceDataProvider::getSystemData()
289 Sequence
<sal_Int8
> rawData
;
292 return [NSData dataWithBytes
: rawData
.getArray() length
: rawData
.getLength()];
295 Any
ByteSequenceDataProvider::getOOoData()
301 unsigned int flavorDataLength
= [mSystemData length
];
302 Sequence
<sal_Int8
> byteSequence
;
303 byteSequence
.realloc(flavorDataLength
);
304 memcpy(byteSequence
.getArray(), [mSystemData bytes
], flavorDataLength
);
305 oOOData
= makeAny(byteSequence
);
316 //###########################
318 class HTMLFormatDataProvider
: public DataProviderBaseImpl
321 HTMLFormatDataProvider(const Any
& data
);
323 HTMLFormatDataProvider(NSData
* data
);
325 virtual NSData
* getSystemData();
327 virtual Any
getOOoData();
330 HTMLFormatDataProvider::HTMLFormatDataProvider(const Any
& data
) :
331 DataProviderBaseImpl(data
)
335 HTMLFormatDataProvider::HTMLFormatDataProvider(NSData
* data
) :
336 DataProviderBaseImpl(data
)
340 NSData
* HTMLFormatDataProvider::getSystemData()
342 Sequence
<sal_Int8
> textHtmlData
;
343 mData
>>= textHtmlData
;
345 Sequence
<sal_Int8
> htmlFormatData
= TextHtmlToHTMLFormat(textHtmlData
);
347 return [NSData dataWithBytes
: htmlFormatData
.getArray() length
: htmlFormatData
.getLength()];
350 Any
HTMLFormatDataProvider::getOOoData()
356 unsigned int flavorDataLength
= [mSystemData length
];
357 Sequence
<sal_Int8
> unkHtmlData
;
359 unkHtmlData
.realloc(flavorDataLength
);
360 memcpy(unkHtmlData
.getArray(), [mSystemData bytes
], flavorDataLength
);
362 Sequence
<sal_Int8
>* pPlainHtml
= &unkHtmlData
;
363 Sequence
<sal_Int8
> plainHtml
;
365 if (isHTMLFormat(unkHtmlData
))
367 plainHtml
= HTMLFormatToTextHtml(unkHtmlData
);
368 pPlainHtml
= &plainHtml
;
371 oOOData
= makeAny(*pPlainHtml
);
381 //###########################
383 class BMPDataProvider
: public DataProviderBaseImpl
386 BMPDataProvider(const Any
& data
);
388 BMPDataProvider(NSData
* data
);
390 virtual NSData
* getSystemData();
392 virtual Any
getOOoData();
395 BMPDataProvider::BMPDataProvider(const Any
& data
) :
396 DataProviderBaseImpl(data
)
400 BMPDataProvider::BMPDataProvider(NSData
* data
) :
401 DataProviderBaseImpl(data
)
405 NSData
* BMPDataProvider::getSystemData()
407 Sequence
<sal_Int8
> bmpData
;
410 Sequence
<sal_Int8
> pictData
;
411 NSData
* sysData
= NULL
;
413 if (BMPtoPICT(bmpData
, pictData
))
415 sysData
= [NSData dataWithBytes
: pictData
.getArray() length
: pictData
.getLength()];
421 /* At the moment the OOo 'PCT' filter is not good enough to be used
422 and there is no flavor defined for exchanging 'PCT' with OOo so
423 we will at the moment convert 'PCT' to a Windows BMP and provide
426 Any
BMPDataProvider::getOOoData()
432 unsigned int flavorDataLength
= [mSystemData length
];
433 Sequence
<sal_Int8
> pictData(flavorDataLength
);
435 memcpy(pictData
.getArray(), [mSystemData bytes
], flavorDataLength
);
437 Sequence
<sal_Int8
> bmpData
;
439 if (PICTtoBMP(pictData
, bmpData
))
441 oOOData
= makeAny(bmpData
);
452 //######################
454 class FileListDataProvider
: public DataProviderBaseImpl
457 FileListDataProvider(const Any
& data
);
458 FileListDataProvider(NSArray
* data
);
460 virtual NSData
* getSystemData();
461 virtual Any
getOOoData();
464 FileListDataProvider::FileListDataProvider(const Any
& data
) :
465 DataProviderBaseImpl(data
)
469 FileListDataProvider::FileListDataProvider(NSArray
* data
) :
470 DataProviderBaseImpl(data
)
474 NSData
* FileListDataProvider::getSystemData()
476 return [NSData data
];
479 Any
FileListDataProvider::getOOoData()
485 size_t length
= [mSystemData count
];
486 size_t lenSeqRequired
= 0;
488 for (size_t i
= 0; i
< length
; i
++)
490 NSString
* fname
= [mSystemData objectAtIndex
: i
];
491 lenSeqRequired
+= [fname maximumLengthOfBytesUsingEncoding
: NSUnicodeStringEncoding
] + sizeof(unichar
);
494 Sequence
<sal_Int8
> oOOFileList(lenSeqRequired
);
495 unichar
* pBuffer
= reinterpret_cast<unichar
*>(oOOFileList
.getArray());
496 rtl_zeroMemory(pBuffer
, lenSeqRequired
);
498 for (size_t i
= 0; i
< length
; i
++)
500 NSString
* fname
= [mSystemData objectAtIndex
: i
];
501 [fname getCharacters
: pBuffer
];
502 size_t l
= [fname length
];
506 oOOData
= makeAny(oOOFileList
);
516 //###########################
518 DataFlavorMapper::DataFlavorMapper()
520 Reference
<XMultiServiceFactory
> mrServiceManager
= vcl::unohelper::GetMultiServiceFactory();
521 mrXMimeCntFactory
= Reference
<XMimeContentTypeFactory
>(mrServiceManager
->createInstance(
522 OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.datatransfer.MimeContentTypeFactory"))), UNO_QUERY
);
524 if (!mrXMimeCntFactory
.is())
525 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM("AquaClipboard: Cannot create com.sun.star.datatransfer.MimeContentTypeFactory")), NULL
);
528 DataFlavor
DataFlavorMapper::systemToOpenOfficeFlavor(NSString
* systemDataFlavor
) const
530 DataFlavor oOOFlavor
;
532 for (size_t i
= 0; i
< SIZE_FLAVOR_MAP
; i
++)
534 if ([systemDataFlavor caseInsensitiveCompare
: flavorMap
[i
].SystemFlavor
] == NSOrderedSame
)
536 oOOFlavor
.MimeType
= OUString::createFromAscii(flavorMap
[i
].OOoFlavor
);
537 oOOFlavor
.HumanPresentableName
= OUString(RTL_CONSTASCII_USTRINGPARAM(flavorMap
[i
].HumanPresentableName
));
538 oOOFlavor
.DataType
= flavorMap
[i
].DataType
;
546 NSString
* DataFlavorMapper::openOfficeToSystemFlavor(const DataFlavor
& oOOFlavor
) const
548 NSString
* sysFlavor
= NULL
;
550 for (size_t i
= 0; i
< SIZE_FLAVOR_MAP
; i
++)
552 if (oOOFlavor
.MimeType
.compareToAscii(flavorMap
[i
].OOoFlavor
, strlen(flavorMap
[i
].OOoFlavor
)) == 0)
554 sysFlavor
= flavorMap
[i
].SystemFlavor
;
561 DataProviderPtr_t
DataFlavorMapper::getDataProvider(NSString
* systemFlavor
, Reference
<XTransferable
> rTransferable
) const
563 DataProviderPtr_t dp
;
567 DataFlavor oOOFlavor
= systemToOpenOfficeFlavor(systemFlavor
);
569 Any data
= rTransferable
->getTransferData(oOOFlavor
);
571 if (isByteSequenceType(data
.getValueType()))
573 if ([systemFlavor caseInsensitiveCompare
: NSHTMLPboardType
] == NSOrderedSame
)
575 dp
= DataProviderPtr_t(new HTMLFormatDataProvider(data
));
577 else if ([systemFlavor caseInsensitiveCompare
: NSPICTPboardType
] == NSOrderedSame
)
579 dp
= DataProviderPtr_t(new BMPDataProvider(data
));
581 else if ([systemFlavor caseInsensitiveCompare
: NSFilenamesPboardType
] == NSOrderedSame
)
583 dp
= DataProviderPtr_t(new FileListDataProvider(data
));
587 dp
= DataProviderPtr_t(new ByteSequenceDataProvider(data
));
590 else // Must be OUString type
592 BOOST_ASSERT(isOUStringType(data
.getValueType()));
593 dp
= DataProviderPtr_t(new UniDataProvider(data
));
596 catch(UnsupportedFlavorException
&)
598 // Somebody violates the contract of the clipboard
599 // interface @see XTransferable
605 DataProviderPtr_t
DataFlavorMapper::getDataProvider(const NSString
* systemFlavor
, NSArray
* systemData
) const
607 return DataProviderPtr_t(new FileListDataProvider(systemData
));
610 DataProviderPtr_t
DataFlavorMapper::getDataProvider(const NSString
* systemFlavor
, NSData
* systemData
) const
612 DataProviderPtr_t dp
;
614 if ([systemFlavor caseInsensitiveCompare
: NSStringPboardType
] == NSOrderedSame
)
616 dp
= DataProviderPtr_t(new UniDataProvider(systemData
));
618 else if ([systemFlavor caseInsensitiveCompare
: NSHTMLPboardType
] == NSOrderedSame
)
620 dp
= DataProviderPtr_t(new HTMLFormatDataProvider(systemData
));
622 else if ([systemFlavor caseInsensitiveCompare
: NSPICTPboardType
] == NSOrderedSame
)
624 dp
= DataProviderPtr_t(new BMPDataProvider(systemData
));
626 else if ([systemFlavor caseInsensitiveCompare
: NSFilenamesPboardType
] == NSOrderedSame
)
628 //dp = DataProviderPtr_t(new FileListDataProvider(systemData));
632 dp
= DataProviderPtr_t(new ByteSequenceDataProvider(systemData
));
638 bool DataFlavorMapper::isValidMimeContentType(const rtl::OUString
& contentType
) const
644 Reference
<XMimeContentType
> xCntType(mrXMimeCntFactory
->createMimeContentType(contentType
));
646 catch( IllegalArgumentException
& )
654 NSArray
* DataFlavorMapper::flavorSequenceToTypesArray(const com::sun::star::uno::Sequence
<com::sun::star::datatransfer::DataFlavor
>& flavors
) const
656 sal_uInt32 nFlavors
= flavors
.getLength();
657 NSMutableArray
* array
= [[NSMutableArray alloc
] initWithCapacity
: 1];
659 for (sal_uInt32 i
= 0; i
< nFlavors
; i
++)
661 NSString
* str
= openOfficeToSystemFlavor(flavors
[i
]);
665 [array addObject
: str
];
670 // in case no system flavor was found to report
671 // report at least one so D&D between OOo targets works
672 if( [array count
] == 0 )
674 [array addObject
: PBTYPE_DUMMY_INTERNAL
];
677 return [array autorelease
];
680 com::sun::star::uno::Sequence
<com::sun::star::datatransfer::DataFlavor
> DataFlavorMapper::typesArrayToFlavorSequence(NSArray
* types
) const
682 int nFormats
= [types count
];
683 Sequence
<DataFlavor
> flavors
;
685 for (int i
= 0; i
< nFormats
; i
++)
687 NSString
* sysFormat
= [types objectAtIndex
: i
];
688 DataFlavor oOOFlavor
= systemToOpenOfficeFlavor(sysFormat
);
690 if (isValidFlavor(oOOFlavor
))
692 flavors
.realloc(flavors
.getLength() + 1);
693 flavors
[flavors
.getLength() - 1] = oOOFlavor
;
701 NSArray
* DataFlavorMapper::getAllSupportedPboardTypes() const
703 NSMutableArray
* array
= [[NSMutableArray alloc
] initWithCapacity
: SIZE_FLAVOR_MAP
];
705 for (sal_uInt32 i
= 0; i
< SIZE_FLAVOR_MAP
; i
++)
707 [array addObject
: flavorMap
[i
].SystemFlavor
];
710 return [array autorelease
];