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/bmp", "Windows Bitmap", CPPUTYPE_SEQINT8 },
129 	  { NSPICTPboardType, "image/bmp", "Windows Bitmap", 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 BMPDataProvider : public DataProviderBaseImpl
375 {
376     NSBitmapImageFileType meImageType;
377 public:
378   BMPDataProvider(const Any& data, NSBitmapImageFileType eImageType );
379 
380   BMPDataProvider(NSData* data, NSBitmapImageFileType eImageType);
381 
382   virtual NSData* getSystemData();
383 
384   virtual Any getOOoData();
385 };
386 
387 BMPDataProvider::BMPDataProvider(const Any& data, NSBitmapImageFileType eImageType) :
388   DataProviderBaseImpl(data),
389   meImageType( eImageType )
390 {
391 }
392 
393 BMPDataProvider::BMPDataProvider(NSData* data, NSBitmapImageFileType eImageType) :
394   DataProviderBaseImpl(data),
395   meImageType( eImageType )
396 {
397 }
398 
399 NSData* BMPDataProvider::getSystemData()
400 {
401   Sequence<sal_Int8> bmpData;
402   mData >>= bmpData;
403 
404   Sequence<sal_Int8> pictData;
405   NSData* sysData = NULL;
406 
407   if (BMPToImage(bmpData, pictData, meImageType))
408 	{
409 	  sysData = [NSData dataWithBytes: pictData.getArray() length: pictData.getLength()];
410 	}
411 
412   return sysData;
413 }
414 
415 /* At the moment the OOo 'PCT' filter is not good enough to be used
416    and there is no flavor defined for exchanging 'PCT' with OOo so
417    we will at the moment convert 'PCT' to a Windows BMP and provide
418    this to OOo
419 */
420 Any BMPDataProvider::getOOoData()
421 {
422   Any oOOData;
423 
424   if (mSystemData)
425 	{
426 	  unsigned int flavorDataLength = [mSystemData length];
427 	  Sequence<sal_Int8> pictData(flavorDataLength);
428 
429 	  memcpy(pictData.getArray(), [mSystemData bytes], flavorDataLength);
430 
431 	  Sequence<sal_Int8> bmpData;
432 
433 	  if (ImageToBMP(pictData, bmpData, meImageType))
434 		{
435 		  oOOData = makeAny(bmpData);
436 		}
437 	}
438   else
439 	{
440 	  oOOData = mData;
441 	}
442 
443   return oOOData;
444 }
445 
446 //######################
447 
448 class FileListDataProvider : public DataProviderBaseImpl
449 {
450 public:
451   FileListDataProvider(const Any& data);
452   FileListDataProvider(NSArray* data);
453 
454   virtual NSData* getSystemData();
455   virtual Any getOOoData();
456 };
457 
458 FileListDataProvider::FileListDataProvider(const Any& data) :
459   DataProviderBaseImpl(data)
460 {
461 }
462 
463 FileListDataProvider::FileListDataProvider(NSArray* data) :
464   DataProviderBaseImpl(data)
465 {
466 }
467 
468 NSData* FileListDataProvider::getSystemData()
469 {
470   return [NSData data];
471 }
472 
473 Any FileListDataProvider::getOOoData()
474 {
475   Any oOOData;
476 
477   if (mSystemData)
478 	{
479 	  size_t length = [mSystemData count];
480 	  size_t lenSeqRequired = 0;
481 
482 	  for (size_t i = 0; i < length; i++)
483 		{
484 		  NSString* fname = [mSystemData objectAtIndex: i];
485 		  lenSeqRequired += [fname maximumLengthOfBytesUsingEncoding: NSUnicodeStringEncoding] + sizeof(unichar);
486 		}
487 
488 	  Sequence<sal_Int8> oOOFileList(lenSeqRequired);
489 	  unichar* pBuffer = reinterpret_cast<unichar*>(oOOFileList.getArray());
490 	  rtl_zeroMemory(pBuffer, lenSeqRequired);
491 
492 	  for (size_t i = 0; i < length; i++)
493 		{
494 		  NSString* fname = [mSystemData objectAtIndex: i];
495 		  [fname getCharacters: pBuffer];
496 		  size_t l = [fname length];
497 		  pBuffer += l + 1;
498 		}
499 
500 	  oOOData = makeAny(oOOFileList);
501 	}
502   else
503 	{
504 	  oOOData = mData;
505 	}
506 
507   return oOOData;
508 }
509 
510 //###########################
511 
512 DataFlavorMapper::DataFlavorMapper()
513 {
514     Reference<XMultiServiceFactory> mrServiceManager = vcl::unohelper::GetMultiServiceFactory();
515     mrXMimeCntFactory = Reference<XMimeContentTypeFactory>(mrServiceManager->createInstance(
516 	   OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.datatransfer.MimeContentTypeFactory"))), UNO_QUERY);
517 
518   if (!mrXMimeCntFactory.is())
519 	throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM("AquaClipboard: Cannot create com.sun.star.datatransfer.MimeContentTypeFactory")), NULL);
520 }
521 
522 DataFlavorMapper::~DataFlavorMapper()
523 {
524     // release potential NSStrings
525     for( OfficeOnlyTypes::iterator it = maOfficeOnlyTypes.begin(); it != maOfficeOnlyTypes.end(); ++it )
526     {
527         [it->second release];
528         it->second = nil;
529     }
530 }
531 
532 DataFlavor DataFlavorMapper::systemToOpenOfficeFlavor(NSString* systemDataFlavor) const
533 {
534   DataFlavor oOOFlavor;
535 
536   for (size_t i = 0; i < SIZE_FLAVOR_MAP; i++)
537 	{
538 	  if ([systemDataFlavor caseInsensitiveCompare: flavorMap[i].SystemFlavor] == NSOrderedSame)
539 		{
540 		  oOOFlavor.MimeType = OUString::createFromAscii(flavorMap[i].OOoFlavor);
541 		  oOOFlavor.HumanPresentableName = OUString(RTL_CONSTASCII_USTRINGPARAM(flavorMap[i].HumanPresentableName));
542 		  oOOFlavor.DataType = flavorMap[i].DataType;
543 		  return oOOFlavor;
544 		}
545 	} // for
546 
547 	// look if this might be an internal type; if it comes in here it must have
548 	// been through openOfficeToSystemFlavor before, so it should then be in the map
549 	rtl::OUString aTryFlavor( NSStringToOUString( systemDataFlavor ) );
550 	if( maOfficeOnlyTypes.find( aTryFlavor ) != maOfficeOnlyTypes.end() )
551 	{
552 	    oOOFlavor.MimeType = aTryFlavor;
553 	    oOOFlavor.HumanPresentableName = rtl::OUString();
554 	    oOOFlavor.DataType = CPPUTYPE_SEQINT8;
555 	}
556 
557 	return oOOFlavor;
558 }
559 
560 NSString* DataFlavorMapper::openOfficeToSystemFlavor(const DataFlavor& oOOFlavor) const
561 {
562     NSString* sysFlavor = NULL;
563 
564 	for( size_t i = 0; i < SIZE_FLAVOR_MAP; ++i )
565 	{
566 	    if (oOOFlavor.MimeType.compareToAscii(flavorMap[i].OOoFlavor, strlen(flavorMap[i].OOoFlavor)) == 0)
567 		{
568 		    sysFlavor = flavorMap[i].SystemFlavor;
569 		}
570 	}
571 
572 	if( ! sysFlavor )
573 	{
574 		OfficeOnlyTypes::const_iterator it = maOfficeOnlyTypes.find( oOOFlavor.MimeType );
575 		if( it == maOfficeOnlyTypes.end() )
576 			sysFlavor = maOfficeOnlyTypes[ oOOFlavor.MimeType ] = OUStringToNSString( oOOFlavor.MimeType );
577 		else
578 			sysFlavor = it->second;
579 	}
580 
581 	return sysFlavor;
582 }
583 
584 NSString* DataFlavorMapper::openOfficeImageToSystemFlavor(NSPasteboard* pPasteboard) const
585 {
586     NSArray *supportedTypes = [NSArray arrayWithObjects: NSTIFFPboardType, NSPICTPboardType, nil];
587     NSString *sysFlavor = [pPasteboard availableTypeFromArray:supportedTypes];
588     return sysFlavor;
589 }
590 
591 DataProviderPtr_t DataFlavorMapper::getDataProvider(NSString* systemFlavor, Reference<XTransferable> rTransferable) const
592 {
593   DataProviderPtr_t dp;
594 
595   try
596 	{
597 	  DataFlavor oOOFlavor = systemToOpenOfficeFlavor(systemFlavor);
598 
599 	  Any data = rTransferable->getTransferData(oOOFlavor);
600 
601 	  if (isByteSequenceType(data.getValueType()))
602 		{
603 		  /*
604 		     the HTMLFormatDataProvider prepends segment information to HTML
605 		     this is useful for exchange with MS Word (which brings this stuff from Windows)
606 		     but annoying for other applications. Since this extension is not a standard datatype
607 		     on the Mac, let us not provide but provide normal HTML
608 
609 		  if ([systemFlavor caseInsensitiveCompare: NSHTMLPboardType] == NSOrderedSame)
610 			{
611 			  dp = DataProviderPtr_t(new HTMLFormatDataProvider(data));
612 			}
613 		  else
614 		  */
615 		  if ([systemFlavor caseInsensitiveCompare: NSPICTPboardType] == NSOrderedSame)
616 			{
617 			  dp = DataProviderPtr_t(new BMPDataProvider(data, PICTImageFileType));
618 			}
619 		  else if ([systemFlavor caseInsensitiveCompare: NSTIFFPboardType] == NSOrderedSame)
620 			{
621 			  dp = DataProviderPtr_t(new BMPDataProvider(data, NSTIFFFileType));
622 			}
623 		  else if ([systemFlavor caseInsensitiveCompare: NSFilenamesPboardType] == NSOrderedSame)
624 			{
625 			  dp = DataProviderPtr_t(new FileListDataProvider(data));
626 			}
627 		  else
628 			{
629 			  dp = DataProviderPtr_t(new ByteSequenceDataProvider(data));
630 			}
631 		}
632 	  else // Must be OUString type
633 		{
634 		  BOOST_ASSERT(isOUStringType(data.getValueType()));
635 		  dp = DataProviderPtr_t(new UniDataProvider(data));
636 		}
637 	}
638   catch(UnsupportedFlavorException&)
639 	{
640 	  // Somebody violates the contract of the clipboard
641 	  // interface @see XTransferable
642 	}
643 
644   return dp;
645 }
646 
647 DataProviderPtr_t DataFlavorMapper::getDataProvider(const NSString* /*systemFlavor*/, NSArray* systemData) const
648 {
649   return DataProviderPtr_t(new FileListDataProvider(systemData));
650 }
651 
652 DataProviderPtr_t DataFlavorMapper::getDataProvider(const NSString* systemFlavor, NSData* systemData) const
653 {
654   DataProviderPtr_t dp;
655 
656   if ([systemFlavor caseInsensitiveCompare: NSStringPboardType] == NSOrderedSame)
657 	{
658 	  dp = DataProviderPtr_t(new UniDataProvider(systemData));
659 	}
660   else if ([systemFlavor caseInsensitiveCompare: NSHTMLPboardType] == NSOrderedSame)
661 	{
662 	  dp = DataProviderPtr_t(new HTMLFormatDataProvider(systemData));
663 	}
664   else if ([systemFlavor caseInsensitiveCompare: NSPICTPboardType] == NSOrderedSame)
665 	{
666 	  dp = DataProviderPtr_t(new BMPDataProvider(systemData, PICTImageFileType));
667 	}
668   else if ([systemFlavor caseInsensitiveCompare: NSTIFFPboardType] == NSOrderedSame)
669 	{
670 	  dp = DataProviderPtr_t(new BMPDataProvider(systemData, NSTIFFFileType));
671 	}
672   else if ([systemFlavor caseInsensitiveCompare: NSFilenamesPboardType] == NSOrderedSame)
673 	{
674 	  //dp = DataProviderPtr_t(new FileListDataProvider(systemData));
675 	}
676   else
677 	{
678 	  dp = DataProviderPtr_t(new ByteSequenceDataProvider(systemData));
679 	}
680 
681   return dp;
682 }
683 
684 bool DataFlavorMapper::isValidMimeContentType(const rtl::OUString& contentType) const
685 {
686   bool result = true;
687 
688   try
689 	{
690 	  Reference<XMimeContentType> xCntType(mrXMimeCntFactory->createMimeContentType(contentType));
691 	}
692   catch( IllegalArgumentException& )
693 	{
694 	  result = false;
695 	}
696 
697   return result;
698 }
699 
700 NSArray* DataFlavorMapper::flavorSequenceToTypesArray(const com::sun::star::uno::Sequence<com::sun::star::datatransfer::DataFlavor>& flavors) const
701 {
702   sal_uInt32 nFlavors = flavors.getLength();
703   NSMutableArray* array = [[NSMutableArray alloc] initWithCapacity: 1];
704 
705   for (sal_uInt32 i = 0; i < nFlavors; i++)
706   {
707       if( flavors[i].MimeType.compareToAscii( "image/bmp", 9 ) == 0 )
708       {
709           [array addObject: NSTIFFPboardType];
710           [array addObject: NSPICTPboardType];
711       }
712       else
713       {
714           NSString* str = openOfficeToSystemFlavor(flavors[i]);
715 
716           if (str != NULL)
717           {
718               [str retain];
719               [array addObject: str];
720           }
721       }
722   }
723 
724    // #i89462# #i90747#
725    // in case no system flavor was found to report
726    // report at least one so D&D between OOo targets works
727   if( [array count] == 0 )
728   {
729       [array addObject: PBTYPE_DUMMY_INTERNAL];
730   }
731 
732   return [array autorelease];
733 }
734 
735 com::sun::star::uno::Sequence<com::sun::star::datatransfer::DataFlavor> DataFlavorMapper::typesArrayToFlavorSequence(NSArray* types) const
736 {
737   int nFormats = [types count];
738   Sequence<DataFlavor> flavors;
739 
740   for (int i = 0; i < nFormats; i++)
741 	{
742 	  NSString* sysFormat = [types objectAtIndex: i];
743 	  DataFlavor oOOFlavor = systemToOpenOfficeFlavor(sysFormat);
744 
745 	  if (isValidFlavor(oOOFlavor))
746 		{
747 		  flavors.realloc(flavors.getLength() + 1);
748 		  flavors[flavors.getLength() - 1] = oOOFlavor;
749 		}
750 	}
751 
752   return flavors;
753 }
754 
755 
756 NSArray* DataFlavorMapper::getAllSupportedPboardTypes() const
757 {
758   NSMutableArray* array = [[NSMutableArray alloc] initWithCapacity: SIZE_FLAVOR_MAP];
759 
760   for (sal_uInt32 i = 0; i < SIZE_FLAVOR_MAP; i++)
761 	{
762 	  [array addObject: flavorMap[i].SystemFlavor];
763 	}
764 
765   return [array autorelease];
766 }
767