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 #include "vcl/unohelp.hxx"
25 #include <DataFlavorMapping.hxx>
26 #include "HtmlFmtFlt.hxx"
27 #include "PictToBmpFlt.hxx"
28 #include "com/sun/star/datatransfer/UnsupportedFlavorException.hpp"
29 #include "com/sun/star/datatransfer/XMimeContentType.hpp"
30 #include "com/sun/star/lang/XMultiServiceFactory.hpp"
31 #include "com/sun/star/uno/Sequence.hxx"
32 
33 #include <rtl/ustring.hxx>
34 #include <rtl/memory.h>
35 #include <osl/endian.h>
36 
37 #include <vector>
38 #include <stdio.h>
39 
40 #include <premac.h>
41 #include <Cocoa/Cocoa.h>
42 #include <postmac.h>
43 
44 using namespace ::com::sun::star::datatransfer;
45 using namespace rtl;
46 using namespace ::com::sun::star::uno;
47 using namespace com::sun::star::lang;
48 using namespace cppu;
49 using namespace std;
50 
51 namespace // private
52 {
53   const Type CPPUTYPE_SEQINT8  = getCppuType((Sequence<sal_Int8>*)0);
54   const Type CPPUTYPE_OUSTRING = getCppuType( (OUString*)0 );
55 
56   /* Determine whether or not a DataFlavor is valid.
57    */
58   bool isValidFlavor(const DataFlavor& aFlavor)
59   {
60 	size_t len = aFlavor.MimeType.getLength();
61 	Type dtype = aFlavor.DataType;
62 	return ((len > 0) && ((dtype == CPPUTYPE_SEQINT8) || (dtype == CPPUTYPE_OUSTRING)));
63   }
64 
65   typedef vector<sal_Unicode> UnicodeBuffer;
66 
67   OUString NSStringToOUString(NSString* cfString)
68   {
69 	BOOST_ASSERT(cfString && "Invalid parameter");
70 
71 	const char* utf8Str = [cfString UTF8String];
72 	unsigned int len = rtl_str_getLength(utf8Str);
73 
74 	return OUString(utf8Str, len, RTL_TEXTENCODING_UTF8);
75   }
76 
77   NSString* OUStringToNSString(const OUString& ustring)
78   {
79 	OString utf8Str = OUStringToOString(ustring, RTL_TEXTENCODING_UTF8);
80 	return [NSString stringWithCString: utf8Str.getStr() encoding: NSUTF8StringEncoding];
81   }
82 
83 
84   const NSString* PBTYPE_UT16 = @"CorePasteboardFlavorType 0x75743136";
85   const NSString* PBTYPE_PICT = @"CorePasteboardFlavorType 0x50494354";
86   const NSString* PBTYPE_HTML = @"CorePasteboardFlavorType 0x48544D4C";
87   const NSString* PBTYPE_SODX = @"application/x-openoffice-objectdescriptor-xml;windows_formatname=\"Star Object Descriptor (XML)\"";
88   const NSString* PBTYPE_SESX = @"application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\"";
89   const NSString* PBTYPE_SLSDX = @"application/x-openoffice-linksrcdescriptor-xml;windows_formatname=\"Star Link Source Descriptor (XML)\"";
90   const NSString* PBTYPE_ESX = @"application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\"";
91   const NSString* PBTYPE_LSX = @"application/x-openoffice-link-source-xml;windows_formatname=\"Star Link Source (XML)\"";
92   const NSString* PBTYPE_EOX = @"application/x-openoffice-embedded-obj-xml;windows_formatname=\"Star Embedded Object (XML)\"";
93   const NSString* PBTYPE_SVXB = @"application/x-openoffice-svbx;windows_formatname=\"SVXB (StarView Bitmap/Animation)\"";
94   const NSString* PBTYPE_GDIMF = @"application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"";
95   const NSString* PBTYPE_WMF = @"application/x-openoffice-wmf;windows_formatname=\"Image WMF\"";
96   const NSString* PBTYPE_EMF = @"application/x-openoffice-emf;windows_formatname=\"Image EMF\"";
97 
98   const NSString* PBTYPE_DUMMY_INTERNAL = @"application/x-openoffice-internal";
99 
100   const char* FLAVOR_SODX = "application/x-openoffice-objectdescriptor-xml;windows_formatname=\"Star Object Descriptor (XML)\"";
101   const char* FLAVOR_SESX = "application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\"";
102   const char* FLAVOR_SLSDX = "application/x-openoffice-linksrcdescriptor-xml;windows_formatname=\"Star Link Source Descriptor (XML)\"";
103   const char* FLAVOR_ESX = "application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\"";
104   const char* FLAVOR_LSX = "application/x-openoffice-link-source-xml;windows_formatname=\"Star Link Source (XML)\"";
105   const char* FLAVOR_EOX = "application/x-openoffice-embedded-obj-xml;windows_formatname=\"Star Embedded Object (XML)\"";
106   const char* FLAVOR_SVXB = "application/x-openoffice-svbx;windows_formatname=\"SVXB (StarView Bitmap/Animation)\"";
107   const char* FLAVOR_GDIMF = "application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"";
108   const char* FLAVOR_WMF = "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"";
109   const char* FLAVOR_EMF = "application/x-openoffice-emf;windows_formatname=\"Image EMF\"";
110 
111   const char* FLAVOR_DUMMY_INTERNAL = "application/x-openoffice-internal";
112 
113 
114   struct FlavorMap
115   {
116 	NSString* SystemFlavor;
117 	const char* OOoFlavor;
118 	const char* HumanPresentableName;
119 	Type DataType;
120   };
121 
122   /* At the moment it appears as if only MS Office pastes "public.html" to the clipboard.
123    */
124   FlavorMap flavorMap[] =
125 	{
126 	  { NSStringPboardType, "text/plain;charset=utf-16", "Unicode Text (UTF-16)", CPPUTYPE_OUSTRING },
127 	  { NSRTFPboardType, "text/richtext", "Rich Text Format", CPPUTYPE_SEQINT8 },
128 	  { NSTIFFPboardType, "image/png", "Portable Network Graphics", CPPUTYPE_SEQINT8 },
129 	  { NSPICTPboardType, "image/png", "Portable Network Graphics", CPPUTYPE_SEQINT8 },
130 	  { NSHTMLPboardType, "text/html", "Plain Html", CPPUTYPE_SEQINT8 },
131 	  { NSFilenamesPboardType, "application/x-openoffice-filelist;windows_formatname=\"FileList\"", "FileList", CPPUTYPE_SEQINT8 },
132 	  { PBTYPE_SESX, FLAVOR_SESX, "Star Embed Source (XML)", CPPUTYPE_SEQINT8 },
133 	  { PBTYPE_SLSDX, FLAVOR_SLSDX, "Star Link Source Descriptor (XML)", CPPUTYPE_SEQINT8 },
134 	  { PBTYPE_ESX, FLAVOR_ESX, "Star Embed Source (XML)", CPPUTYPE_SEQINT8 },
135 	  { PBTYPE_LSX, FLAVOR_LSX, "Star Link Source (XML)", CPPUTYPE_SEQINT8 },
136 	  { PBTYPE_EOX, FLAVOR_EOX, "Star Embedded Object (XML)", CPPUTYPE_SEQINT8 },
137 	  { PBTYPE_SVXB, FLAVOR_SVXB, "SVXB (StarView Bitmap/Animation", CPPUTYPE_SEQINT8 },
138 	  { PBTYPE_GDIMF, FLAVOR_GDIMF, "GDIMetaFile", CPPUTYPE_SEQINT8 },
139 	  { PBTYPE_WMF, FLAVOR_WMF, "Windows MetaFile", CPPUTYPE_SEQINT8 },
140 	  { PBTYPE_EMF, FLAVOR_EMF, "Windows Enhanced MetaFile", CPPUTYPE_SEQINT8 },
141 	  { PBTYPE_SODX, FLAVOR_SODX, "Star Object Descriptor (XML)", CPPUTYPE_SEQINT8 },
142       { PBTYPE_DUMMY_INTERNAL, FLAVOR_DUMMY_INTERNAL, "internal data",CPPUTYPE_SEQINT8 }
143 	};
144 
145 
146   #define SIZE_FLAVOR_MAP (sizeof(flavorMap)/sizeof(FlavorMap))
147 
148 
149   inline bool isByteSequenceType(const Type& theType)
150   {
151 	return (theType == CPPUTYPE_SEQINT8);
152   }
153 
154   inline bool isOUStringType(const Type& theType)
155   {
156 	return (theType == CPPUTYPE_OUSTRING);
157   }
158 
159 } // namespace private
160 
161 
162 //###########################
163 
164 /* A base class for other data provider.
165  */
166 class DataProviderBaseImpl : public DataProvider
167 {
168 public:
169   DataProviderBaseImpl(const Any& data);
170   DataProviderBaseImpl(id data);
171   virtual ~DataProviderBaseImpl();
172 
173 protected:
174   Any mData;
175   //NSData* mSystemData;
176   id mSystemData;
177 };
178 
179 DataProviderBaseImpl::DataProviderBaseImpl(const Any& data) :
180   mData(data),
181   mSystemData(nil)
182 {
183 }
184 
185 DataProviderBaseImpl::DataProviderBaseImpl(id data) :
186   mSystemData(data)
187 {
188   [mSystemData retain];
189 }
190 
191 
192 DataProviderBaseImpl::~DataProviderBaseImpl()
193 {
194   if (mSystemData)
195 	{
196 	  [mSystemData release];
197 	}
198 }
199 
200 //#################################
201 
202 class UniDataProvider : public DataProviderBaseImpl
203 {
204 public:
205   UniDataProvider(const Any& data);
206 
207   UniDataProvider(NSData* data);
208 
209   virtual NSData* getSystemData();
210 
211   virtual Any getOOoData();
212 };
213 
214 UniDataProvider::UniDataProvider(const Any& data) :
215   DataProviderBaseImpl(data)
216 {
217 }
218 
219 UniDataProvider::UniDataProvider(NSData* data) :
220   DataProviderBaseImpl(data)
221 {
222 }
223 
224 NSData* UniDataProvider::getSystemData()
225 {
226   OUString ustr;
227   mData >>= ustr;
228 
229   OString strUtf8;
230   ustr.convertToString(&strUtf8, RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS);
231 
232   return [NSData dataWithBytes: strUtf8.getStr() length: strUtf8.getLength()];
233 }
234 
235 Any UniDataProvider::getOOoData()
236 {
237   Any oOOData;
238 
239   if (mSystemData)
240 	{
241 	  oOOData = makeAny(OUString(reinterpret_cast<const sal_Char*>([mSystemData bytes]),
242 								 [mSystemData length],
243 								 RTL_TEXTENCODING_UTF8));
244 	}
245   else
246 	{
247 	  oOOData = mData;
248 	}
249 
250   return oOOData;
251 }
252 
253 //###########################
254 
255 class ByteSequenceDataProvider : public DataProviderBaseImpl
256 {
257 public:
258   ByteSequenceDataProvider(const Any& data);
259 
260   ByteSequenceDataProvider(NSData* data);
261 
262   virtual NSData* getSystemData();
263 
264   virtual Any getOOoData();
265 };
266 
267 ByteSequenceDataProvider::ByteSequenceDataProvider(const Any& data) :
268   DataProviderBaseImpl(data)
269 {
270 }
271 
272 ByteSequenceDataProvider::ByteSequenceDataProvider(NSData* data) :
273   DataProviderBaseImpl(data)
274 {
275 }
276 
277 
278 NSData* ByteSequenceDataProvider::getSystemData()
279 {
280    Sequence<sal_Int8> rawData;
281    mData >>= rawData;
282 
283    return [NSData dataWithBytes: rawData.getArray()	length: rawData.getLength()];
284 }
285 
286 Any ByteSequenceDataProvider::getOOoData()
287 {
288   Any oOOData;
289 
290   if (mSystemData)
291 	{
292 	  unsigned int flavorDataLength = [mSystemData length];
293 	  Sequence<sal_Int8> byteSequence;
294 	  byteSequence.realloc(flavorDataLength);
295 	  memcpy(byteSequence.getArray(), [mSystemData bytes], flavorDataLength);
296 	  oOOData = makeAny(byteSequence);
297 	}
298   else
299 	{
300 	  oOOData =  mData;
301 	}
302 
303   return oOOData;
304 }
305 
306 
307 //###########################
308 
309 class HTMLFormatDataProvider : public DataProviderBaseImpl
310 {
311 public:
312   HTMLFormatDataProvider(const Any& data);
313 
314   HTMLFormatDataProvider(NSData* data);
315 
316   virtual NSData* getSystemData();
317 
318   virtual Any getOOoData();
319 };
320 
321 HTMLFormatDataProvider::HTMLFormatDataProvider(const Any& data) :
322   DataProviderBaseImpl(data)
323 {
324 }
325 
326 HTMLFormatDataProvider::HTMLFormatDataProvider(NSData* data) :
327   DataProviderBaseImpl(data)
328 {
329 }
330 
331 NSData* HTMLFormatDataProvider::getSystemData()
332 {
333   Sequence<sal_Int8> textHtmlData;
334   mData >>= textHtmlData;
335 
336   Sequence<sal_Int8> htmlFormatData = TextHtmlToHTMLFormat(textHtmlData);
337 
338   return [NSData dataWithBytes: htmlFormatData.getArray() length: htmlFormatData.getLength()];
339 }
340 
341 Any HTMLFormatDataProvider::getOOoData()
342 {
343   Any oOOData;
344 
345   if (mSystemData)
346 	{
347 	  unsigned int flavorDataLength = [mSystemData length];
348 	  Sequence<sal_Int8> unkHtmlData;
349 
350 	  unkHtmlData.realloc(flavorDataLength);
351 	  memcpy(unkHtmlData.getArray(), [mSystemData bytes], flavorDataLength);
352 
353 	  Sequence<sal_Int8>* pPlainHtml = &unkHtmlData;
354 	  Sequence<sal_Int8> plainHtml;
355 
356 	  if (isHTMLFormat(unkHtmlData))
357 		{
358 		  plainHtml = HTMLFormatToTextHtml(unkHtmlData);
359 		  pPlainHtml = &plainHtml;
360 		}
361 
362 	  oOOData = makeAny(*pPlainHtml);
363 	}
364   else
365 	{
366 	  oOOData = mData;
367 	}
368 
369   return oOOData;
370 }
371 
372 //###########################
373 
374 class PNGDataProvider : public DataProviderBaseImpl
375 {
376 	NSBitmapImageFileType meImageType;
377 public:
378 	PNGDataProvider( const Any&, NSBitmapImageFileType);
379 
380 	PNGDataProvider( NSData*, NSBitmapImageFileType);
381 
382 	virtual NSData* getSystemData();
383 
384 	virtual Any getOOoData();
385 };
386 
387 PNGDataProvider::PNGDataProvider( const Any& data, NSBitmapImageFileType eImageType) :
388   DataProviderBaseImpl(data),
389   meImageType( eImageType )
390 {
391 }
392 
393 PNGDataProvider::PNGDataProvider( NSData* data, NSBitmapImageFileType eImageType) :
394   DataProviderBaseImpl(data),
395   meImageType( eImageType )
396 {
397 }
398 
399 NSData* PNGDataProvider::getSystemData()
400 {
401 	Sequence<sal_Int8> pngData;
402 	mData >>= pngData;
403 
404 	Sequence<sal_Int8> imgData;
405 	NSData* sysData = NULL;
406 	if( PNGToImage( pngData, imgData, meImageType))
407 		sysData = [NSData dataWithBytes: imgData.getArray() length: imgData.getLength()];
408 
409 	return sysData;
410 }
411 
412 /* The AOO 'PCT' filter is not yet good enough to be used
413    and there is no flavor defined for exchanging 'PCT' with AOO
414    so we convert 'PCT' to a PNG and provide this to AOO
415 */
416 Any PNGDataProvider::getOOoData()
417 {
418 	Any oOOData;
419 
420 	if( mSystemData)
421 	{
422 		const unsigned int flavorDataLength = [mSystemData length];
423 		Sequence<sal_Int8> imgData( flavorDataLength);
424 		memcpy( imgData.getArray(), [mSystemData bytes], flavorDataLength);
425 
426 		Sequence<sal_Int8> pngData;
427 		if( ImageToPNG( imgData, pngData, meImageType))
428 			oOOData = makeAny( pngData);
429 	}
430 	else
431 	{
432 		oOOData = mData;
433 	}
434 
435   return oOOData;
436 }
437 
438 //######################
439 
440 class FileListDataProvider : public DataProviderBaseImpl
441 {
442 public:
443   FileListDataProvider(const Any& data);
444   FileListDataProvider(NSArray* data);
445 
446   virtual NSData* getSystemData();
447   virtual Any getOOoData();
448 };
449 
450 FileListDataProvider::FileListDataProvider(const Any& data) :
451   DataProviderBaseImpl(data)
452 {
453 }
454 
455 FileListDataProvider::FileListDataProvider(NSArray* data) :
456   DataProviderBaseImpl(data)
457 {
458 }
459 
460 NSData* FileListDataProvider::getSystemData()
461 {
462   return [NSData data];
463 }
464 
465 Any FileListDataProvider::getOOoData()
466 {
467   Any oOOData;
468 
469   if (mSystemData)
470 	{
471 	  size_t length = [mSystemData count];
472 	  size_t lenSeqRequired = 0;
473 
474 	  for (size_t i = 0; i < length; i++)
475 		{
476 		  NSString* fname = [mSystemData objectAtIndex: i];
477 		  lenSeqRequired += [fname maximumLengthOfBytesUsingEncoding: NSUnicodeStringEncoding] + sizeof(unichar);
478 		}
479 
480 	  Sequence<sal_Int8> oOOFileList(lenSeqRequired);
481 	  unichar* pBuffer = reinterpret_cast<unichar*>(oOOFileList.getArray());
482 	  rtl_zeroMemory(pBuffer, lenSeqRequired);
483 
484 	  for (size_t i = 0; i < length; i++)
485 		{
486 		  NSString* fname = [mSystemData objectAtIndex: i];
487 		  [fname getCharacters: pBuffer];
488 		  size_t l = [fname length];
489 		  pBuffer += l + 1;
490 		}
491 
492 	  oOOData = makeAny(oOOFileList);
493 	}
494   else
495 	{
496 	  oOOData = mData;
497 	}
498 
499   return oOOData;
500 }
501 
502 //###########################
503 
504 DataFlavorMapper::DataFlavorMapper()
505 {
506     Reference<XMultiServiceFactory> mrServiceManager = vcl::unohelper::GetMultiServiceFactory();
507     mrXMimeCntFactory = Reference<XMimeContentTypeFactory>(mrServiceManager->createInstance(
508 	   OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.datatransfer.MimeContentTypeFactory"))), UNO_QUERY);
509 
510   if (!mrXMimeCntFactory.is())
511 	throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM("AquaClipboard: Cannot create com.sun.star.datatransfer.MimeContentTypeFactory")), NULL);
512 }
513 
514 DataFlavorMapper::~DataFlavorMapper()
515 {
516     // release potential NSStrings
517     for( OfficeOnlyTypes::iterator it = maOfficeOnlyTypes.begin(); it != maOfficeOnlyTypes.end(); ++it )
518     {
519         [it->second release];
520         it->second = nil;
521     }
522 }
523 
524 DataFlavor DataFlavorMapper::systemToOpenOfficeFlavor(NSString* systemDataFlavor) const
525 {
526   DataFlavor oOOFlavor;
527 
528   for (size_t i = 0; i < SIZE_FLAVOR_MAP; i++)
529 	{
530 	  if ([systemDataFlavor caseInsensitiveCompare: flavorMap[i].SystemFlavor] == NSOrderedSame)
531 		{
532 		  oOOFlavor.MimeType = OUString::createFromAscii( flavorMap[i].OOoFlavor);
533 		  oOOFlavor.HumanPresentableName = OUString::createFromAscii( flavorMap[i].HumanPresentableName);
534 		  oOOFlavor.DataType = flavorMap[i].DataType;
535 		  return oOOFlavor;
536 		}
537 	} // for
538 
539 	// look if this might be an internal type; if it comes in here it must have
540 	// been through openOfficeToSystemFlavor before, so it should then be in the map
541 	rtl::OUString aTryFlavor( NSStringToOUString( systemDataFlavor ) );
542 	if( maOfficeOnlyTypes.find( aTryFlavor ) != maOfficeOnlyTypes.end() )
543 	{
544 	    oOOFlavor.MimeType = aTryFlavor;
545 	    oOOFlavor.HumanPresentableName = rtl::OUString();
546 	    oOOFlavor.DataType = CPPUTYPE_SEQINT8;
547 	}
548 
549 	return oOOFlavor;
550 }
551 
552 NSString* DataFlavorMapper::openOfficeToSystemFlavor(const DataFlavor& oOOFlavor, bool& rbInternal) const
553 {
554     NSString* sysFlavor = NULL;
555     rbInternal = false;
556 
557 	for( size_t i = 0; i < SIZE_FLAVOR_MAP; ++i )
558 	{
559 	    if (oOOFlavor.MimeType.compareToAscii(flavorMap[i].OOoFlavor, strlen(flavorMap[i].OOoFlavor)) == 0)
560 		{
561 		    sysFlavor = flavorMap[i].SystemFlavor;
562 		}
563 	}
564 
565     if(!sysFlavor)
566     {
567         rbInternal = true;
568         OfficeOnlyTypes::const_iterator it = maOfficeOnlyTypes.find( oOOFlavor.MimeType );
569 
570         if( it == maOfficeOnlyTypes.end() )
571             sysFlavor = maOfficeOnlyTypes[ oOOFlavor.MimeType ] = OUStringToNSString( oOOFlavor.MimeType );
572         else
573             sysFlavor = it->second;
574     }
575 
576     return sysFlavor;
577 }
578 
579 NSString* DataFlavorMapper::openOfficeImageToSystemFlavor(NSPasteboard* pPasteboard) const
580 {
581     NSArray *supportedTypes = [NSArray arrayWithObjects: NSTIFFPboardType, NSPICTPboardType, nil];
582     NSString *sysFlavor = [pPasteboard availableTypeFromArray:supportedTypes];
583     return sysFlavor;
584 }
585 
586 DataProviderPtr_t DataFlavorMapper::getDataProvider(NSString* systemFlavor, Reference<XTransferable> rTransferable) const
587 {
588   DataProviderPtr_t dp;
589 
590   try
591 	{
592 	  DataFlavor oOOFlavor = systemToOpenOfficeFlavor(systemFlavor);
593 
594 	  Any data = rTransferable->getTransferData(oOOFlavor);
595 
596 	  if (isByteSequenceType(data.getValueType()))
597 		{
598 		  /*
599 		     the HTMLFormatDataProvider prepends segment information to HTML
600 		     this is useful for exchange with MS Word (which brings this stuff from Windows)
601 		     but annoying for other applications. Since this extension is not a standard datatype
602 		     on the Mac, let us not provide but provide normal HTML
603 
604 		  if ([systemFlavor caseInsensitiveCompare: NSHTMLPboardType] == NSOrderedSame)
605 			{
606 			  dp = DataProviderPtr_t(new HTMLFormatDataProvider(data));
607 			}
608 		  else
609 		  */
610 		  if ([systemFlavor caseInsensitiveCompare: NSPICTPboardType] == NSOrderedSame)
611 			{
612 			  dp = DataProviderPtr_t( new PNGDataProvider( data, PICTImageFileType));
613 			}
614 		  else if ([systemFlavor caseInsensitiveCompare: NSTIFFPboardType] == NSOrderedSame)
615 			{
616 			  dp = DataProviderPtr_t( new PNGDataProvider( data, NSTIFFFileType));
617 			}
618 		  else if ([systemFlavor caseInsensitiveCompare: NSFilenamesPboardType] == NSOrderedSame)
619 			{
620 			  dp = DataProviderPtr_t(new FileListDataProvider(data));
621 			}
622 		  else
623 			{
624 			  dp = DataProviderPtr_t(new ByteSequenceDataProvider(data));
625 			}
626 		}
627 	  else // Must be OUString type
628 		{
629 		  BOOST_ASSERT(isOUStringType(data.getValueType()));
630 		  dp = DataProviderPtr_t(new UniDataProvider(data));
631 		}
632 	}
633   catch(UnsupportedFlavorException&)
634 	{
635 	  // Somebody violates the contract of the clipboard
636 	  // interface @see XTransferable
637 	}
638 
639   return dp;
640 }
641 
642 DataProviderPtr_t DataFlavorMapper::getDataProvider(const NSString* /*systemFlavor*/, NSArray* systemData) const
643 {
644   return DataProviderPtr_t(new FileListDataProvider(systemData));
645 }
646 
647 DataProviderPtr_t DataFlavorMapper::getDataProvider(const NSString* systemFlavor, NSData* systemData) const
648 {
649   DataProviderPtr_t dp;
650 
651   if ([systemFlavor caseInsensitiveCompare: NSStringPboardType] == NSOrderedSame)
652 	{
653 	  dp = DataProviderPtr_t(new UniDataProvider(systemData));
654 	}
655   else if ([systemFlavor caseInsensitiveCompare: NSHTMLPboardType] == NSOrderedSame)
656 	{
657 	  dp = DataProviderPtr_t(new HTMLFormatDataProvider(systemData));
658 	}
659   else if ([systemFlavor caseInsensitiveCompare: NSPICTPboardType] == NSOrderedSame)
660 	{
661 	  dp = DataProviderPtr_t( new PNGDataProvider(systemData, PICTImageFileType));
662 	}
663   else if ([systemFlavor caseInsensitiveCompare: NSTIFFPboardType] == NSOrderedSame)
664 	{
665 	  dp = DataProviderPtr_t( new PNGDataProvider(systemData, NSTIFFFileType));
666 	}
667   else if ([systemFlavor caseInsensitiveCompare: NSFilenamesPboardType] == NSOrderedSame)
668 	{
669 	  //dp = DataProviderPtr_t(new FileListDataProvider(systemData));
670 	}
671   else
672 	{
673 	  dp = DataProviderPtr_t(new ByteSequenceDataProvider(systemData));
674 	}
675 
676   return dp;
677 }
678 
679 bool DataFlavorMapper::isValidMimeContentType(const rtl::OUString& contentType) const
680 {
681   bool result = true;
682 
683   try
684 	{
685 	  Reference<XMimeContentType> xCntType(mrXMimeCntFactory->createMimeContentType(contentType));
686 	}
687   catch( IllegalArgumentException& )
688 	{
689 	  result = false;
690 	}
691 
692   return result;
693 }
694 
695 NSArray* DataFlavorMapper::flavorSequenceToTypesArray(const com::sun::star::uno::Sequence<com::sun::star::datatransfer::DataFlavor>& flavors) const
696 {
697   sal_uInt32 nFlavors = flavors.getLength();
698   NSMutableArray* array = [[NSMutableArray alloc] initWithCapacity: 1];
699 
700   bool bNeedDummyInternalFlavor(false);
701 
702   for (sal_uInt32 i = 0; i < nFlavors; i++)
703   {
704       if( flavors[i].MimeType.compareToAscii( "image/bmp", 9 ) == 0 )
705       {
706           [array addObject: NSTIFFPboardType];
707           [array addObject: NSPICTPboardType];
708       }
709       else
710       {
711           NSString* str = openOfficeToSystemFlavor(flavors[i], bNeedDummyInternalFlavor);
712 
713           if (str != NULL)
714           {
715               [str retain];
716               [array addObject: str];
717           }
718       }
719   }
720 
721    // #i89462# #i90747#
722    // in case no system flavor was found to report
723    // report at least one so D&D between OOo targets works
724   if( [array count] == 0 || bNeedDummyInternalFlavor)
725   {
726       [array addObject: PBTYPE_DUMMY_INTERNAL];
727   }
728 
729   return [array autorelease];
730 }
731 
732 com::sun::star::uno::Sequence<com::sun::star::datatransfer::DataFlavor> DataFlavorMapper::typesArrayToFlavorSequence(NSArray* types) const
733 {
734   int nFormats = [types count];
735   Sequence<DataFlavor> flavors;
736 
737   for (int i = 0; i < nFormats; i++)
738 	{
739 	  NSString* sysFormat = [types objectAtIndex: i];
740 	  DataFlavor oOOFlavor = systemToOpenOfficeFlavor(sysFormat);
741 
742 	  if (isValidFlavor(oOOFlavor))
743 		{
744 		  flavors.realloc(flavors.getLength() + 1);
745 		  flavors[flavors.getLength() - 1] = oOOFlavor;
746 		}
747 	}
748 
749   return flavors;
750 }
751 
752 
753 NSArray* DataFlavorMapper::getAllSupportedPboardTypes() const
754 {
755   NSMutableArray* array = [[NSMutableArray alloc] initWithCapacity: SIZE_FLAVOR_MAP];
756 
757   for (sal_uInt32 i = 0; i < SIZE_FLAVOR_MAP; i++)
758 	{
759 	  [array addObject: flavorMap[i].SystemFlavor];
760 	}
761 
762   return [array autorelease];
763 }
764