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 <DataFlavorMapping.hxx>
32 #include "HtmlFmtFlt.hxx"
33 #include "PictToBmpFlt.hxx"
34 #include <com/sun/star/datatransfer/UnsupportedFlavorException.hpp>
35 #include <com/sun/star/datatransfer/XMimeContentType.hpp>
36 #include "com/sun/star/uno/Sequence.hxx"
38 #include <rtl/ustring.hxx>
39 #include <rtl/memory.h>
40 #include <osl/endian.h>
46 #include <QuickTime/QuickTime.h>
49 using namespace ::com::sun::star::datatransfer
;
51 using namespace ::com::sun::star::uno
;
52 using namespace com::sun::star::lang
;
58 const Type CPPUTYPE_SEQINT8
= getCppuType((Sequence
<sal_Int8
>*)0);
59 const Type CPPUTYPE_OUSTRING
= getCppuType( (OUString
*)0 );
61 /* Determine whether or not a DataFlavor is valid.
63 bool isValidFlavor(const DataFlavor
& aFlavor
)
65 size_t len
= aFlavor
.MimeType
.getLength();
66 Type dtype
= aFlavor
.DataType
;
67 return ((len
> 0) && ((dtype
== CPPUTYPE_SEQINT8
) || (dtype
== CPPUTYPE_OUSTRING
)));
70 typedef vector
<sal_Unicode
> UnicodeBuffer
;
72 OUString
NSStringToOUString(NSString
* cfString
)
74 BOOST_ASSERT(cfString
&& "Invalid parameter");
76 const char* utf8Str
= [cfString UTF8String
];
77 unsigned int len
= rtl_str_getLength(utf8Str
);
79 return OUString(utf8Str
, len
, RTL_TEXTENCODING_UTF8
);
82 NSString
* OUStringToNSString(const OUString
& ustring
)
84 OString utf8Str
= OUStringToOString(ustring
, RTL_TEXTENCODING_UTF8
);
85 return [NSString stringWithCString
: utf8Str
.getStr() encoding
: NSUTF8StringEncoding
];
89 const NSString
* PBTYPE_UT16
= @
"CorePasteboardFlavorType 0x75743136";
90 const NSString
* PBTYPE_PICT
= @
"CorePasteboardFlavorType 0x50494354";
91 const NSString
* PBTYPE_HTML
= @
"CorePasteboardFlavorType 0x48544D4C";
92 const NSString
* PBTYPE_SODX
= @
"application/x-openoffice-objectdescriptor-xml;windows_formatname=\"Star Object Descriptor (XML)\"";
93 const NSString
* PBTYPE_SESX
= @
"application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\"";
94 const NSString
* PBTYPE_SLSDX
= @
"application/x-openoffice-linksrcdescriptor-xml;windows_formatname=\"Star Link Source Descriptor (XML)\"";
95 const NSString
* PBTYPE_ESX
= @
"application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\"";
96 const NSString
* PBTYPE_LSX
= @
"application/x-openoffice-link-source-xml;windows_formatname=\"Star Link Source (XML)\"";
97 const NSString
* PBTYPE_EOX
= @
"application/x-openoffice-embedded-obj-xml;windows_formatname=\"Star Embedded Object (XML)\"";
98 const NSString
* PBTYPE_SVXB
= @
"application/x-openoffice-svbx;windows_formatname=\"SVXB (StarView Bitmap/Animation)\"";
99 const NSString
* PBTYPE_GDIMF
= @
"application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"";
100 const NSString
* PBTYPE_WMF
= @
"application/x-openoffice-wmf;windows_formatname=\"Image WMF\"";
101 const NSString
* PBTYPE_EMF
= @
"application/x-openoffice-emf;windows_formatname=\"Image EMF\"";
103 const NSString
* PBTYPE_DUMMY_INTERNAL
= @
"application/x-openoffice-internal";
105 const char* FLAVOR_SODX
= "application/x-openoffice-objectdescriptor-xml;windows_formatname=\"Star Object Descriptor (XML)\"";
106 const char* FLAVOR_SESX
= "application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\"";
107 const char* FLAVOR_SLSDX
= "application/x-openoffice-linksrcdescriptor-xml;windows_formatname=\"Star Link Source Descriptor (XML)\"";
108 const char* FLAVOR_ESX
= "application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\"";
109 const char* FLAVOR_LSX
= "application/x-openoffice-link-source-xml;windows_formatname=\"Star Link Source (XML)\"";
110 const char* FLAVOR_EOX
= "application/x-openoffice-embedded-obj-xml;windows_formatname=\"Star Embedded Object (XML)\"";
111 const char* FLAVOR_SVXB
= "application/x-openoffice-svbx;windows_formatname=\"SVXB (StarView Bitmap/Animation)\"";
112 const char* FLAVOR_GDIMF
= "application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"";
113 const char* FLAVOR_WMF
= "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"";
114 const char* FLAVOR_EMF
= "application/x-openoffice-emf;windows_formatname=\"Image EMF\"";
116 const char* FLAVOR_DUMMY_INTERNAL
= "application/x-openoffice-internal";
121 NSString
* SystemFlavor
;
122 const char* OOoFlavor
;
123 const char* HumanPresentableName
;
127 /* At the moment it appears as if only MS Office pastes "public.html" to the clipboard.
129 FlavorMap flavorMap
[] =
131 { NSStringPboardType
, "text/plain;charset=utf-16", "Unicode Text (UTF-16)", CPPUTYPE_OUSTRING
},
132 { NSRTFPboardType
, "text/richtext", "Rich Text Format", CPPUTYPE_SEQINT8
},
133 { NSPICTPboardType
, "image/bmp", "Windows Bitmap", CPPUTYPE_SEQINT8
},
134 { NSHTMLPboardType
, "text/html", "Plain Html", CPPUTYPE_SEQINT8
},
135 { NSFilenamesPboardType
, "application/x-openoffice-filelist;windows_formatname=\"FileList\"", "FileList", CPPUTYPE_SEQINT8
},
136 { PBTYPE_SESX
, FLAVOR_SESX
, "Star Embed Source (XML)", CPPUTYPE_SEQINT8
},
137 { PBTYPE_SLSDX
, FLAVOR_SLSDX
, "Star Link Source Descriptor (XML)", CPPUTYPE_SEQINT8
},
138 { PBTYPE_ESX
, FLAVOR_ESX
, "Star Embed Source (XML)", CPPUTYPE_SEQINT8
},
139 { PBTYPE_LSX
, FLAVOR_LSX
, "Star Link Source (XML)", CPPUTYPE_SEQINT8
},
140 { PBTYPE_EOX
, FLAVOR_EOX
, "Star Embedded Object (XML)", CPPUTYPE_SEQINT8
},
141 { PBTYPE_SVXB
, FLAVOR_SVXB
, "SVXB (StarView Bitmap/Animation", CPPUTYPE_SEQINT8
},
142 { PBTYPE_GDIMF
, FLAVOR_GDIMF
, "GDIMetaFile", CPPUTYPE_SEQINT8
},
143 { PBTYPE_WMF
, FLAVOR_WMF
, "Windows MetaFile", CPPUTYPE_SEQINT8
},
144 { PBTYPE_EMF
, FLAVOR_EMF
, "Windows Enhanced MetaFile", CPPUTYPE_SEQINT8
},
145 { PBTYPE_SODX
, FLAVOR_SODX
, "Star Object Descriptor (XML)", CPPUTYPE_SEQINT8
},
146 { PBTYPE_DUMMY_INTERNAL
, FLAVOR_DUMMY_INTERNAL
, "internal data",CPPUTYPE_SEQINT8
}
147 // { PBTYPE_UT16, "text/plain;charset=utf-16", "Unicode Text (UTF-16)", CPPUTYPE_OUSTRING }
148 // { kUTTypePICT, @"PICT", "image/x-macpict;windows_formatname=\"Mac Pict\"", "Mac Pict", CPPUTYPE_SEQINT8 }
149 // { kUTTypeHTML, @"HTML", "text/html", "Plain Html", CPPUTYPE_SEQINT8 }
153 #define SIZE_FLAVOR_MAP (sizeof(flavorMap)/sizeof(FlavorMap))
156 inline bool isByteSequenceType(const Type
& theType
)
158 return (theType
== CPPUTYPE_SEQINT8
);
161 inline bool isOUStringType(const Type
& theType
)
163 return (theType
== CPPUTYPE_OUSTRING
);
166 } // namespace private
169 //###########################
171 /* A base class for other data provider.
173 class DataProviderBaseImpl
: public DataProvider
176 DataProviderBaseImpl(const Any
& data
);
177 DataProviderBaseImpl(id data
);
178 virtual ~DataProviderBaseImpl();
182 //NSData* mSystemData;
186 DataProviderBaseImpl::DataProviderBaseImpl(const Any
& data
) :
192 DataProviderBaseImpl::DataProviderBaseImpl(id data
) :
195 [mSystemData retain
];
199 DataProviderBaseImpl::~DataProviderBaseImpl()
203 [mSystemData release
];
207 //#################################
209 class UniDataProvider
: public DataProviderBaseImpl
212 UniDataProvider(const Any
& data
);
214 UniDataProvider(NSData
* data
);
216 virtual NSData
* getSystemData();
218 virtual Any
getOOoData();
221 UniDataProvider::UniDataProvider(const Any
& data
) :
222 DataProviderBaseImpl(data
)
226 UniDataProvider::UniDataProvider(NSData
* data
) :
227 DataProviderBaseImpl(data
)
231 NSData
* UniDataProvider::getSystemData()
237 ustr
.convertToString(&strUtf8
, RTL_TEXTENCODING_UTF8
, OUSTRING_TO_OSTRING_CVTFLAGS
);
239 return [NSData dataWithBytes
: strUtf8
.getStr() length
: strUtf8
.getLength()];
242 Any
UniDataProvider::getOOoData()
248 oOOData
= makeAny(OUString(reinterpret_cast<const sal_Char
*>([mSystemData bytes
]),
249 [mSystemData length
],
250 RTL_TEXTENCODING_UTF8
));
260 //###########################
262 class ByteSequenceDataProvider
: public DataProviderBaseImpl
265 ByteSequenceDataProvider(const Any
& data
);
267 ByteSequenceDataProvider(NSData
* data
);
269 virtual NSData
* getSystemData();
271 virtual Any
getOOoData();
274 ByteSequenceDataProvider::ByteSequenceDataProvider(const Any
& data
) :
275 DataProviderBaseImpl(data
)
279 ByteSequenceDataProvider::ByteSequenceDataProvider(NSData
* data
) :
280 DataProviderBaseImpl(data
)
285 NSData
* ByteSequenceDataProvider::getSystemData()
287 Sequence
<sal_Int8
> rawData
;
290 return [NSData dataWithBytes
: rawData
.getArray() length
: rawData
.getLength()];
293 Any
ByteSequenceDataProvider::getOOoData()
299 unsigned int flavorDataLength
= [mSystemData length
];
300 Sequence
<sal_Int8
> byteSequence
;
301 byteSequence
.realloc(flavorDataLength
);
302 memcpy(byteSequence
.getArray(), [mSystemData bytes
], flavorDataLength
);
303 oOOData
= makeAny(byteSequence
);
314 //###########################
316 class HTMLFormatDataProvider
: public DataProviderBaseImpl
319 HTMLFormatDataProvider(const Any
& data
);
321 HTMLFormatDataProvider(NSData
* data
);
323 virtual NSData
* getSystemData();
325 virtual Any
getOOoData();
328 HTMLFormatDataProvider::HTMLFormatDataProvider(const Any
& data
) :
329 DataProviderBaseImpl(data
)
333 HTMLFormatDataProvider::HTMLFormatDataProvider(NSData
* data
) :
334 DataProviderBaseImpl(data
)
338 NSData
* HTMLFormatDataProvider::getSystemData()
340 Sequence
<sal_Int8
> textHtmlData
;
341 mData
>>= textHtmlData
;
343 Sequence
<sal_Int8
> htmlFormatData
= TextHtmlToHTMLFormat(textHtmlData
);
345 return [NSData dataWithBytes
: htmlFormatData
.getArray() length
: htmlFormatData
.getLength()];
348 Any
HTMLFormatDataProvider::getOOoData()
354 unsigned int flavorDataLength
= [mSystemData length
];
355 Sequence
<sal_Int8
> unkHtmlData
;
357 unkHtmlData
.realloc(flavorDataLength
);
358 memcpy(unkHtmlData
.getArray(), [mSystemData bytes
], flavorDataLength
);
360 Sequence
<sal_Int8
>* pPlainHtml
= &unkHtmlData
;
361 Sequence
<sal_Int8
> plainHtml
;
363 if (isHTMLFormat(unkHtmlData
))
365 plainHtml
= HTMLFormatToTextHtml(unkHtmlData
);
366 pPlainHtml
= &plainHtml
;
369 oOOData
= makeAny(*pPlainHtml
);
379 //###########################
381 class BMPDataProvider
: public DataProviderBaseImpl
384 BMPDataProvider(const Any
& data
);
386 BMPDataProvider(NSData
* data
);
388 virtual NSData
* getSystemData();
390 virtual Any
getOOoData();
393 BMPDataProvider::BMPDataProvider(const Any
& data
) :
394 DataProviderBaseImpl(data
)
398 BMPDataProvider::BMPDataProvider(NSData
* data
) :
399 DataProviderBaseImpl(data
)
403 NSData
* BMPDataProvider::getSystemData()
405 Sequence
<sal_Int8
> bmpData
;
408 Sequence
<sal_Int8
> pictData
;
409 NSData
* sysData
= NULL
;
411 if (BMPtoPICT(bmpData
, pictData
))
413 sysData
= [NSData dataWithBytes
: pictData
.getArray() length
: pictData
.getLength()];
419 /* At the moment the OOo 'PCT' filter is not good enough to be used
420 and there is no flavor defined for exchanging 'PCT' with OOo so
421 we will at the moment convert 'PCT' to a Windows BMP and provide
424 Any
BMPDataProvider::getOOoData()
430 unsigned int flavorDataLength
= [mSystemData length
];
431 Sequence
<sal_Int8
> pictData(flavorDataLength
);
433 memcpy(pictData
.getArray(), [mSystemData bytes
], flavorDataLength
);
435 Sequence
<sal_Int8
> bmpData
;
437 if (PICTtoBMP(pictData
, bmpData
))
439 oOOData
= makeAny(bmpData
);
450 //######################
452 class FileListDataProvider
: public DataProviderBaseImpl
455 FileListDataProvider(const Any
& data
);
456 FileListDataProvider(NSArray
* data
);
458 virtual NSData
* getSystemData();
459 virtual Any
getOOoData();
462 FileListDataProvider::FileListDataProvider(const Any
& data
) :
463 DataProviderBaseImpl(data
)
467 FileListDataProvider::FileListDataProvider(NSArray
* data
) :
468 DataProviderBaseImpl(data
)
472 NSData
* FileListDataProvider::getSystemData()
474 return [NSData data
];
477 Any
FileListDataProvider::getOOoData()
483 size_t length
= [mSystemData count
];
484 size_t lenSeqRequired
= 0;
486 for (size_t i
= 0; i
< length
; i
++)
488 NSString
* fname
= [mSystemData objectAtIndex
: i
];
489 lenSeqRequired
+= [fname maximumLengthOfBytesUsingEncoding
: NSUnicodeStringEncoding
] + sizeof(unichar
);
492 Sequence
<sal_Int8
> oOOFileList(lenSeqRequired
);
493 unichar
* pBuffer
= reinterpret_cast<unichar
*>(oOOFileList
.getArray());
494 rtl_zeroMemory(pBuffer
, lenSeqRequired
);
496 for (size_t i
= 0; i
< length
; i
++)
498 NSString
* fname
= [mSystemData objectAtIndex
: i
];
499 [fname getCharacters
: pBuffer
];
500 size_t l
= [fname length
];
504 oOOData
= makeAny(oOOFileList
);
514 //###########################
516 DataFlavorMapper::DataFlavorMapper(const Reference
<XComponentContext
>& context
) :
517 mXComponentContext(context
)
519 Reference
<XMultiComponentFactory
> mrServiceManager
= mXComponentContext
->getServiceManager();
520 mrXMimeCntFactory
= Reference
<XMimeContentTypeFactory
>(mrServiceManager
->createInstanceWithContext(
521 OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.datatransfer.MimeContentTypeFactory")), mXComponentContext
), UNO_QUERY
);
523 if (!mrXMimeCntFactory
.is())
524 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM("AquaClipboard: Cannot create com.sun.star.datatransfer.MimeContentTypeFactory")), NULL
);
527 DataFlavor
DataFlavorMapper::systemToOpenOfficeFlavor(NSString
* systemDataFlavor
) const
529 DataFlavor oOOFlavor
;
531 for (size_t i
= 0; i
< SIZE_FLAVOR_MAP
; i
++)
533 if ([systemDataFlavor caseInsensitiveCompare
: flavorMap
[i
].SystemFlavor
] == NSOrderedSame
)
535 oOOFlavor
.MimeType
= OUString::createFromAscii(flavorMap
[i
].OOoFlavor
);
536 oOOFlavor
.HumanPresentableName
= OUString(RTL_CONSTASCII_USTRINGPARAM(flavorMap
[i
].HumanPresentableName
));
537 oOOFlavor
.DataType
= flavorMap
[i
].DataType
;
545 NSString
* DataFlavorMapper::openOfficeToSystemFlavor(const DataFlavor
& oOOFlavor
) const
547 NSString
* sysFlavor
= NULL
;
549 for (size_t i
= 0; i
< SIZE_FLAVOR_MAP
; i
++)
551 if (oOOFlavor
.MimeType
.compareToAscii(flavorMap
[i
].OOoFlavor
, strlen(flavorMap
[i
].OOoFlavor
)) == 0)
553 sysFlavor
= flavorMap
[i
].SystemFlavor
;
560 DataProviderPtr_t
DataFlavorMapper::getDataProvider(NSString
* systemFlavor
, Reference
<XTransferable
> rTransferable
) const
562 DataProviderPtr_t dp
;
566 DataFlavor oOOFlavor
= systemToOpenOfficeFlavor(systemFlavor
);
568 Any data
= rTransferable
->getTransferData(oOOFlavor
);
570 if (isByteSequenceType(data
.getValueType()))
572 if ([systemFlavor caseInsensitiveCompare
: NSHTMLPboardType
] == NSOrderedSame
)
574 dp
= DataProviderPtr_t(new HTMLFormatDataProvider(data
));
576 else if ([systemFlavor caseInsensitiveCompare
: NSPICTPboardType
] == NSOrderedSame
)
578 dp
= DataProviderPtr_t(new BMPDataProvider(data
));
580 else if ([systemFlavor caseInsensitiveCompare
: NSFilenamesPboardType
] == NSOrderedSame
)
582 dp
= DataProviderPtr_t(new FileListDataProvider(data
));
586 dp
= DataProviderPtr_t(new ByteSequenceDataProvider(data
));
589 else // Must be OUString type
591 BOOST_ASSERT(isOUStringType(data
.getValueType()));
592 dp
= DataProviderPtr_t(new UniDataProvider(data
));
595 catch(UnsupportedFlavorException
&)
597 // Somebody violates the contract of the clipboard
598 // interface @see XTransferable
604 DataProviderPtr_t
DataFlavorMapper::getDataProvider(const NSString
* systemFlavor
, NSArray
* systemData
) const
606 return DataProviderPtr_t(new FileListDataProvider(systemData
));
609 DataProviderPtr_t
DataFlavorMapper::getDataProvider(const NSString
* systemFlavor
, NSData
* systemData
) const
611 DataProviderPtr_t dp
;
613 if ([systemFlavor caseInsensitiveCompare
: NSStringPboardType
] == NSOrderedSame
)
615 dp
= DataProviderPtr_t(new UniDataProvider(systemData
));
617 else if ([systemFlavor caseInsensitiveCompare
: NSHTMLPboardType
] == NSOrderedSame
)
619 dp
= DataProviderPtr_t(new HTMLFormatDataProvider(systemData
));
621 else if ([systemFlavor caseInsensitiveCompare
: NSPICTPboardType
] == NSOrderedSame
)
623 dp
= DataProviderPtr_t(new BMPDataProvider(systemData
));
625 else if ([systemFlavor caseInsensitiveCompare
: NSFilenamesPboardType
] == NSOrderedSame
)
627 //dp = DataProviderPtr_t(new FileListDataProvider(systemData));
631 dp
= DataProviderPtr_t(new ByteSequenceDataProvider(systemData
));
637 bool DataFlavorMapper::isValidMimeContentType(const rtl::OUString
& contentType
) const
643 Reference
<XMimeContentType
> xCntType(mrXMimeCntFactory
->createMimeContentType(contentType
));
645 catch( IllegalArgumentException
& )
653 NSArray
* DataFlavorMapper::flavorSequenceToTypesArray(const com::sun::star::uno::Sequence
<com::sun::star::datatransfer::DataFlavor
>& flavors
) const
655 sal_uInt32 nFlavors
= flavors
.getLength();
656 NSMutableArray
* array
= [[NSMutableArray alloc
] initWithCapacity
: 1];
658 for (sal_uInt32 i
= 0; i
< nFlavors
; i
++)
660 NSString
* str
= openOfficeToSystemFlavor(flavors
[i
]);
664 [array addObject
: str
];
669 // in case no system flavor was found to report
670 // report at least one so D&D between OOo targets works
671 if( [array count
] == 0 )
673 [array addObject
: PBTYPE_DUMMY_INTERNAL
];
676 return [array autorelease
];
679 com::sun::star::uno::Sequence
<com::sun::star::datatransfer::DataFlavor
> DataFlavorMapper::typesArrayToFlavorSequence(NSArray
* types
) const
681 int nFormats
= [types count
];
682 Sequence
<DataFlavor
> flavors
;
684 for (int i
= 0; i
< nFormats
; i
++)
686 NSString
* sysFormat
= [types objectAtIndex
: i
];
687 DataFlavor oOOFlavor
= systemToOpenOfficeFlavor(sysFormat
);
689 if (isValidFlavor(oOOFlavor
))
691 flavors
.realloc(flavors
.getLength() + 1);
692 flavors
[flavors
.getLength() - 1] = oOOFlavor
;
700 NSArray
* DataFlavorMapper::getAllSupportedPboardTypes() const
702 NSMutableArray
* array
= [[NSMutableArray alloc
] initWithCapacity
: SIZE_FLAVOR_MAP
];
704 for (sal_uInt32 i
= 0; i
< SIZE_FLAVOR_MAP
; i
++)
706 [array addObject
: flavorMap
[i
].SystemFlavor
];
709 return [array autorelease
];