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