1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20 #include <sal/config.h>
21 #include <sal/log.hxx>
22
23 #include "DataFlavorMapping.hxx"
24 #include "HtmlFmtFlt.hxx"
25 #include "PictToBmpFlt.hxx"
26 #include <com/sun/star/datatransfer/UnsupportedFlavorException.hpp>
27 #include <com/sun/star/datatransfer/XMimeContentType.hpp>
28 #include <com/sun/star/datatransfer/MimeContentTypeFactory.hpp>
29 #include <com/sun/star/lang/IllegalArgumentException.hpp>
30 #include <com/sun/star/uno/Sequence.hxx>
31 #include <comphelper/processfactory.hxx>
32
33 #include <rtl/ustring.hxx>
34 #include <osl/endian.h>
35
36 #include <cassert>
37 #include <string.h>
38 #include <string_view>
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 ::com::sun::star::uno;
46 using namespace com::sun::star::lang;
47 using namespace cppu;
48 using namespace std;
49
50 namespace
51 {
52 /* Determine whether or not a DataFlavor is valid.
53 */
isValidFlavor(const DataFlavor & aFlavor)54 bool isValidFlavor(const DataFlavor& aFlavor)
55 {
56 size_t len = aFlavor.MimeType.getLength();
57 Type dtype = aFlavor.DataType;
58 return ((len > 0) && ((dtype == cppu::UnoType<Sequence<sal_Int8>>::get()) || (dtype == cppu::UnoType<OUString>::get())));
59 }
60
NSStringToOUString(const NSString * cfString)61 OUString NSStringToOUString( const NSString* cfString)
62 {
63 assert(cfString && "Invalid parameter");
64
65 const char* utf8Str = [cfString UTF8String];
66 unsigned int len = rtl_str_getLength(utf8Str);
67
68 return OUString(utf8Str, len, RTL_TEXTENCODING_UTF8);
69 }
70
OUStringToNSString(std::u16string_view ustring)71 NSString* OUStringToNSString(std::u16string_view ustring)
72 {
73 OString utf8Str = OUStringToOString(ustring, RTL_TEXTENCODING_UTF8);
74 return [NSString stringWithCString: utf8Str.getStr() encoding: NSUTF8StringEncoding];
75 }
76
77 const char* FLAVOR_SESX = "application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\"";
78 const char* FLAVOR_SLSDX = "application/x-openoffice-linksrcdescriptor-xml;windows_formatname=\"Star Link Source Descriptor (XML)\"";
79 const char* FLAVOR_ESX = "application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\"";
80 const char* FLAVOR_LSX = "application/x-openoffice-link-source-xml;windows_formatname=\"Star Link Source (XML)\"";
81 const char* FLAVOR_EOX = "application/x-openoffice-embedded-obj-xml;windows_formatname=\"Star Embedded Object (XML)\"";
82 const char* FLAVOR_SVXB = "application/x-openoffice-svbx;windows_formatname=\"SVXB (StarView Bitmap/Animation)\"";
83 const char* FLAVOR_GDIMF = "application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"";
84 const char* FLAVOR_WMF = "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"";
85 const char* FLAVOR_EMF = "application/x-openoffice-emf;windows_formatname=\"Image EMF\"";
86 const char* FLAVOR_SODX = "application/x-openoffice-objectdescriptor-xml;windows_formatname=\"Star Object Descriptor (XML)\"";
87 const char* FLAVOR_LINK = "application/x-openoffice-link;windows_formatname=\"Link\"";
88 const char* FLAVOR_DUMMY_INTERNAL = "application/x-openoffice-internal";
89
90 struct FlavorMap
91 {
92 const NSString* SystemFlavor;
93 const char* OOoFlavor;
94 const char* HumanPresentableName;
95 bool DataTypeOUString; // sequence<byte> otherwise
96 };
97
98 // This is a list of the bidirectional mapping between (internal) MIME types and (system)
99 // pasteboard types.
100
101 // Only pasteboard types mentioned here will be recognized, mapped, and available for pasting in a
102 // fresh LibreOffice process. When copy-pasting in-process, the situation is different.
103
104 // Also MIME types not mentioned here will be stored on the pasteboard (using the same type name),
105 // though. But that is IMHO a bit pointless as they in general won't then be pasteable anyway in a
106 // new LibreOffice process. See the use of the maOfficeOnlyTypes array.
107
108 // The SystemFlavor member is nil for the cases where there is no predefined pasteboard type UTI
109 // and we use the internal MIME type (media type) also on the pasteboard. That is OK in macOS,
110 // there is no requirement that the types are well-formed UTIs. It is different on iOS, I think,
111 // though. For an introduction to UTIs, see for instance
112 // https://alastairs-place.net/blog/2012/06/06/utis-are-better-than-you-think-and-heres-why/
113 //
114 // In those cases the MIME type might actually have parameters appended, separated by semicolons.
115 // At least the FLAVOR_SODX one must have at least a typename="%PRODUCTNAME %PRODUCTVERSION
116 // Spreadsheet" parameter (with macros expanded and translated) for LO to recognise it. See
117 // lcl_TestFormat() in sc/source/ui/view/cellsh.cxx.
118
119 const FlavorMap flavorMap[] =
120 {
121 { NSPasteboardTypeString, "text/plain;charset=utf-16", "Unicode Text (UTF-16)", true },
122 { NSPasteboardTypeRTF, "text/rtf", "Rich Text Format", false },
123 { NSPasteboardTypePDF, "application/pdf", "PDF File", false },
124 { NSPasteboardTypeTIFF, "image/png", "Portable Network Graphics", false },
125 { NSPasteboardTypeHTML, "text/html", "Plain Html", false },
126 SAL_WNODEPRECATED_DECLARATIONS_PUSH
127 // "'NSFilenamesPboardType' is deprecated: first deprecated in macOS 10.14 - Create
128 // multiple pasteboard items with NSPasteboardTypeFileURL or kUTTypeFileURL instead"
129 { NSFilenamesPboardType, "application/x-openoffice-filelist;windows_formatname=\"FileList\"", "FileList", false },
130 SAL_WNODEPRECATED_DECLARATIONS_POP
131 { nil, FLAVOR_SESX, "Star Embed Source (XML)", false },
132 { nil, FLAVOR_SLSDX, "Star Link Source Descriptor (XML)", false },
133 { nil, FLAVOR_ESX, "Star Embed Source (XML)", false },
134 { nil, FLAVOR_LSX, "Star Link Source (XML)", false },
135 { nil, FLAVOR_EOX, "Star Embedded Object (XML)", false },
136 { nil, FLAVOR_SVXB, "SVXB (StarView Bitmap/Animation", false },
137 { nil, FLAVOR_GDIMF, "GDIMetaFile", false },
138 { nil, FLAVOR_WMF, "Windows MetaFile", false },
139 { nil, FLAVOR_EMF, "Windows Enhanced MetaFile", false },
140 { nil, FLAVOR_SODX, "Star Object Descriptor (XML)", false },
141 { nil, FLAVOR_LINK, "Dynamic Data Exchange (DDE link)", false },
142 { nil, FLAVOR_DUMMY_INTERNAL, "internal data",false }
143 };
144
145 #define SIZE_FLAVOR_MAP (sizeof(flavorMap)/sizeof(FlavorMap))
146
isByteSequenceType(const Type & theType)147 bool isByteSequenceType(const Type& theType)
148 {
149 return (theType == cppu::UnoType<Sequence<sal_Int8>>::get());
150 }
151
isOUStringType(const Type & theType)152 bool isOUStringType(const Type& theType)
153 {
154 return (theType == cppu::UnoType<OUString>::get() );
155 }
156
157 /* A base class for other data provider.
158 */
159 class DataProviderBaseImpl : public DataProvider
160 {
161 public:
162 DataProviderBaseImpl(const Any& data);
163 DataProviderBaseImpl(id data);
164 virtual ~DataProviderBaseImpl() override;
165
166 protected:
167 Any mData;
168 //NSData* mSystemData;
169 id mSystemData;
170 };
171
172 } // unnamed namespace
173
DataProviderBaseImpl(const Any & data)174 DataProviderBaseImpl::DataProviderBaseImpl(const Any& data) :
175 mData(data),
176 mSystemData(nil)
177 {
178 }
179
DataProviderBaseImpl(id data)180 DataProviderBaseImpl::DataProviderBaseImpl(id data) :
181 mSystemData(data)
182 {
183 [mSystemData retain];
184 }
185
~DataProviderBaseImpl()186 DataProviderBaseImpl::~DataProviderBaseImpl()
187 {
188 if (mSystemData)
189 {
190 [mSystemData release];
191 }
192 }
193
194 namespace {
195
196 class UniDataProvider : public DataProviderBaseImpl
197 {
198 public:
199 UniDataProvider(const Any& data);
200
201 UniDataProvider(NSData* data);
202
203 virtual NSData* getSystemData() override;
204
205 virtual Any getOOoData() override;
206 };
207
208 }
209
UniDataProvider(const Any & data)210 UniDataProvider::UniDataProvider(const Any& data) :
211 DataProviderBaseImpl(data)
212 {
213 }
214
UniDataProvider(NSData * data)215 UniDataProvider::UniDataProvider(NSData* data) :
216 DataProviderBaseImpl(data)
217 {
218 }
219
getSystemData()220 NSData* UniDataProvider::getSystemData()
221 {
222 OUString ustr;
223 mData >>= ustr;
224
225 OString strUtf8;
226 ustr.convertToString(&strUtf8, RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS);
227
228 return [NSData dataWithBytes: strUtf8.getStr() length: strUtf8.getLength()];
229 }
230
getOOoData()231 Any UniDataProvider::getOOoData()
232 {
233 Any oOOData;
234
235 if (mSystemData)
236 {
237 oOOData <<= OUString(static_cast<const char*>([mSystemData bytes]),
238 [mSystemData length],
239 RTL_TEXTENCODING_UTF8);
240 }
241 else
242 {
243 oOOData = mData;
244 }
245
246 return oOOData;
247 }
248
249 namespace {
250
251 class ByteSequenceDataProvider : public DataProviderBaseImpl
252 {
253 public:
254 ByteSequenceDataProvider(const Any& data);
255
256 ByteSequenceDataProvider(NSData* data);
257
258 virtual NSData* getSystemData() override;
259
260 virtual Any getOOoData() override;
261 };
262
263 }
264
ByteSequenceDataProvider(const Any & data)265 ByteSequenceDataProvider::ByteSequenceDataProvider(const Any& data) :
266 DataProviderBaseImpl(data)
267 {
268 }
269
ByteSequenceDataProvider(NSData * data)270 ByteSequenceDataProvider::ByteSequenceDataProvider(NSData* data) :
271 DataProviderBaseImpl(data)
272 {
273 }
274
getSystemData()275 NSData* ByteSequenceDataProvider::getSystemData()
276 {
277 Sequence<sal_Int8> rawData;
278 mData >>= rawData;
279
280 return [NSData dataWithBytes: rawData.getArray() length: rawData.getLength()];
281 }
282
getOOoData()283 Any ByteSequenceDataProvider::getOOoData()
284 {
285 Any oOOData;
286
287 if (mSystemData)
288 {
289 unsigned int flavorDataLength = [mSystemData length];
290 Sequence<sal_Int8> byteSequence;
291 byteSequence.realloc(flavorDataLength);
292 memcpy(byteSequence.getArray(), [mSystemData bytes], flavorDataLength);
293 oOOData <<= byteSequence;
294 }
295 else
296 {
297 oOOData = mData;
298 }
299
300 return oOOData;
301 }
302
303 namespace {
304
305 class HTMLFormatDataProvider : public DataProviderBaseImpl
306 {
307 public:
308 HTMLFormatDataProvider(NSData* data);
309
310 virtual NSData* getSystemData() override;
311
312 virtual Any getOOoData() override;
313 };
314
315 }
316
HTMLFormatDataProvider(NSData * data)317 HTMLFormatDataProvider::HTMLFormatDataProvider(NSData* data) :
318 DataProviderBaseImpl(data)
319 {
320 }
321
getSystemData()322 NSData* HTMLFormatDataProvider::getSystemData()
323 {
324 Sequence<sal_Int8> textHtmlData;
325 mData >>= textHtmlData;
326
327 Sequence<sal_Int8> htmlFormatData = TextHtmlToHTMLFormat(textHtmlData);
328
329 return [NSData dataWithBytes: htmlFormatData.getArray() length: htmlFormatData.getLength()];
330 }
331
getOOoData()332 Any HTMLFormatDataProvider::getOOoData()
333 {
334 Any oOOData;
335
336 if (mSystemData)
337 {
338 unsigned int flavorDataLength = [mSystemData length];
339 Sequence<sal_Int8> unkHtmlData;
340
341 unkHtmlData.realloc(flavorDataLength);
342 memcpy(unkHtmlData.getArray(), [mSystemData bytes], flavorDataLength);
343
344 Sequence<sal_Int8>* pPlainHtml = &unkHtmlData;
345 Sequence<sal_Int8> plainHtml;
346
347 if (isHTMLFormat(unkHtmlData))
348 {
349 plainHtml = HTMLFormatToTextHtml(unkHtmlData);
350 pPlainHtml = &plainHtml;
351 }
352
353 oOOData <<= *pPlainHtml;
354 }
355 else
356 {
357 oOOData = mData;
358 }
359
360 return oOOData;
361 }
362
363 namespace {
364
365
366 class PNGDataProvider : public DataProviderBaseImpl
367 {
368 NSBitmapImageFileType meImageType;
369 public:
370 PNGDataProvider( const Any&, NSBitmapImageFileType);
371
372 PNGDataProvider( NSData*, NSBitmapImageFileType);
373
374 virtual NSData* getSystemData() override;
375
376 virtual Any getOOoData() override;
377 };
378
379 }
380
PNGDataProvider(const Any & data,NSBitmapImageFileType eImageType)381 PNGDataProvider::PNGDataProvider( const Any& data, NSBitmapImageFileType eImageType) :
382 DataProviderBaseImpl(data),
383 meImageType( eImageType )
384 {
385 }
386
PNGDataProvider(NSData * data,NSBitmapImageFileType eImageType)387 PNGDataProvider::PNGDataProvider( NSData* data, NSBitmapImageFileType eImageType) :
388 DataProviderBaseImpl(data),
389 meImageType( eImageType )
390 {
391 }
392
getSystemData()393 NSData* PNGDataProvider::getSystemData()
394 {
395 Sequence<sal_Int8> pngData;
396 mData >>= pngData;
397
398 Sequence<sal_Int8> imgData;
399 NSData* sysData = nullptr;
400 if( PNGToImage( pngData, imgData, meImageType))
401 sysData = [NSData dataWithBytes: imgData.getArray() length: imgData.getLength()];
402
403 return sysData;
404 }
405
406 /* The AOO 'PCT' filter is not yet good enough to be used
407 and there is no flavor defined for exchanging 'PCT' with AOO
408 so we convert 'PCT' to a PNG and provide this to AOO
409 */
getOOoData()410 Any PNGDataProvider::getOOoData()
411 {
412 Any oOOData;
413
414 if( mSystemData)
415 {
416 const unsigned int flavorDataLength = [mSystemData length];
417 Sequence<sal_Int8> imgData( flavorDataLength);
418 memcpy( imgData.getArray(), [mSystemData bytes], flavorDataLength);
419
420 Sequence<sal_Int8> pngData;
421 if( ImageToPNG( imgData, pngData))
422 oOOData <<= pngData;
423 }
424 else
425 {
426 oOOData = mData;
427 }
428
429 return oOOData;
430 }
431
432 namespace {
433
434 class FileListDataProvider : public DataProviderBaseImpl
435 {
436 public:
437 FileListDataProvider(const Any& data);
438 FileListDataProvider(NSArray* data);
439
440 virtual NSData* getSystemData() override;
441 virtual Any getOOoData() override;
442 };
443
444 }
445
FileListDataProvider(const Any & data)446 FileListDataProvider::FileListDataProvider(const Any& data) :
447 DataProviderBaseImpl(data)
448 {
449 }
450
FileListDataProvider(NSArray * data)451 FileListDataProvider::FileListDataProvider(NSArray* data) :
452 DataProviderBaseImpl(data)
453 {
454 }
455
getSystemData()456 NSData* FileListDataProvider::getSystemData()
457 {
458 return [NSData data];
459 }
460
getOOoData()461 Any FileListDataProvider::getOOoData()
462 {
463 Any oOOData;
464
465 if (mSystemData)
466 {
467 size_t length = [mSystemData count];
468 size_t lenSeqRequired = 0;
469
470 for (size_t i = 0; i < length; i++)
471 {
472 NSString* fname = [mSystemData objectAtIndex: i];
473 lenSeqRequired += [fname maximumLengthOfBytesUsingEncoding: NSUnicodeStringEncoding] + sizeof(unichar);
474 }
475
476 Sequence<sal_Int8> oOOFileList(lenSeqRequired);
477 unichar* pBuffer = reinterpret_cast<unichar*>(oOOFileList.getArray());
478 memset(pBuffer, 0, lenSeqRequired);
479
480 for (size_t i = 0; i < length; i++)
481 {
482 NSString* fname = [mSystemData objectAtIndex: i];
483 [fname getCharacters: pBuffer];
484 size_t l = [fname length];
485 pBuffer += l + 1;
486 }
487
488 oOOData <<= oOOFileList;
489 }
490 else
491 {
492 oOOData = mData;
493 }
494
495 return oOOData;
496 }
497
DataFlavorMapper()498 DataFlavorMapper::DataFlavorMapper()
499 {
500 Reference<XComponentContext> xContext = comphelper::getProcessComponentContext();
501 mrXMimeCntFactory = MimeContentTypeFactory::create( xContext );
502 }
503
~DataFlavorMapper()504 DataFlavorMapper::~DataFlavorMapper()
505 {
506 // release potential NSStrings
507 for( OfficeOnlyTypes::iterator it = maOfficeOnlyTypes.begin(); it != maOfficeOnlyTypes.end(); ++it )
508 {
509 [it->second release];
510 it->second = nil;
511 }
512 }
513
systemToOpenOfficeFlavor(const NSString * systemDataFlavor) const514 DataFlavor DataFlavorMapper::systemToOpenOfficeFlavor( const NSString* systemDataFlavor) const
515 {
516 DataFlavor oOOFlavor;
517
518 for (size_t i = 0; i < SIZE_FLAVOR_MAP; i++)
519 {
520 if ((flavorMap[i].SystemFlavor == nil && ([systemDataFlavor isEqualToString:[NSString stringWithUTF8String:flavorMap[i].OOoFlavor]]
521 ||
522 [systemDataFlavor hasPrefix:[[NSString stringWithUTF8String:flavorMap[i].OOoFlavor] stringByAppendingString:@";"]]))
523 ||
524 (flavorMap[i].SystemFlavor != nil && [systemDataFlavor isEqualToString:const_cast<NSString*>(flavorMap[i].SystemFlavor)]))
525 {
526 if (flavorMap[i].SystemFlavor == nil)
527 oOOFlavor.MimeType = NSStringToOUString(systemDataFlavor);
528 else
529 oOOFlavor.MimeType = OUString::createFromAscii(flavorMap[i].OOoFlavor);
530 oOOFlavor.HumanPresentableName = OUString::createFromAscii(flavorMap[i].HumanPresentableName);
531 oOOFlavor.DataType = flavorMap[i].DataTypeOUString ? cppu::UnoType<OUString>::get() : cppu::UnoType<Sequence<sal_Int8>>::get();
532 return oOOFlavor;
533 }
534 } // for
535
536 // look if this might be an internal type; if it comes in here it must have
537 // been through openOfficeToSystemFlavor before, so it should then be in the map
538 OUString aTryFlavor( NSStringToOUString( systemDataFlavor ) );
539 if( maOfficeOnlyTypes.find( aTryFlavor ) != maOfficeOnlyTypes.end() )
540 {
541 oOOFlavor.MimeType = aTryFlavor;
542 oOOFlavor.HumanPresentableName.clear();
543 oOOFlavor.DataType = cppu::UnoType<Sequence<sal_Int8>>::get();
544 }
545
546 return oOOFlavor;
547 }
548
openOfficeToSystemFlavor(const DataFlavor & oOOFlavor,bool & rbInternal) const549 const NSString* DataFlavorMapper::openOfficeToSystemFlavor( const DataFlavor& oOOFlavor, bool& rbInternal) const
550 {
551 const NSString* sysFlavor = nullptr;
552 rbInternal = false;
553
554 for( size_t i = 0; i < SIZE_FLAVOR_MAP; ++i )
555 {
556 if (oOOFlavor.MimeType.startsWith(OUString::createFromAscii(flavorMap[i].OOoFlavor)))
557 {
558 if (flavorMap[i].SystemFlavor != nil)
559 sysFlavor = flavorMap[i].SystemFlavor;
560 else
561 sysFlavor = OUStringToNSString(oOOFlavor.MimeType);
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
openOfficeImageToSystemFlavor(NSPasteboard * pPasteboard)579 NSString* DataFlavorMapper::openOfficeImageToSystemFlavor(NSPasteboard* pPasteboard)
580 {
581 NSArray *supportedTypes = [NSArray arrayWithObjects: NSPasteboardTypeTIFF, nil];
582 NSString *sysFlavor = [pPasteboard availableTypeFromArray:supportedTypes];
583 return sysFlavor;
584 }
585
getDataProvider(const NSString * systemFlavor,Reference<XTransferable> const & rTransferable) const586 DataProviderPtr_t DataFlavorMapper::getDataProvider( const NSString* systemFlavor, Reference<XTransferable> const & 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: NSPasteboardTypeTIFF] == NSOrderedSame)
611 {
612 dp = DataProviderPtr_t( new PNGDataProvider( data, NSBitmapImageFileTypeTIFF));
613 }
614 SAL_WNODEPRECATED_DECLARATIONS_PUSH
615 // "'NSFilenamesPboardType' is deprecated: first deprecated in macOS 10.14 - Create
616 // multiple pasteboard items with NSPasteboardTypeFileURL or kUTTypeFileURL instead"
617 else if ([systemFlavor caseInsensitiveCompare: NSFilenamesPboardType] == NSOrderedSame)
618 SAL_WNODEPRECATED_DECLARATIONS_POP
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 SAL_WARN_IF(
630 !isOUStringType(data.getValueType()), "vcl",
631 "must be OUString type");
632 dp = DataProviderPtr_t(new UniDataProvider(data));
633 }
634 }
635 catch( const UnsupportedFlavorException& e )
636 {
637 SAL_WARN( "vcl.osx.clipboard", "DataFlavorMapper::getDataProvider(): Exception: " << e.Message );
638 // Somebody violates the contract of the clipboard
639 // interface @see XTransferable
640 }
641
642 return dp;
643 }
644
getDataProvider(const NSString *,NSArray * systemData)645 DataProviderPtr_t DataFlavorMapper::getDataProvider( const NSString* /*systemFlavor*/, NSArray* systemData)
646 {
647 return DataProviderPtr_t(new FileListDataProvider(systemData));
648 }
649
getDataProvider(const NSString * systemFlavor,NSData * systemData)650 DataProviderPtr_t DataFlavorMapper::getDataProvider( const NSString* systemFlavor, NSData* systemData)
651 {
652 DataProviderPtr_t dp;
653
654 if ([systemFlavor caseInsensitiveCompare: NSPasteboardTypeString] == NSOrderedSame)
655 {
656 dp = DataProviderPtr_t(new UniDataProvider(systemData));
657 }
658 else if ([systemFlavor caseInsensitiveCompare: NSPasteboardTypeHTML] == NSOrderedSame)
659 {
660 dp = DataProviderPtr_t(new HTMLFormatDataProvider(systemData));
661 }
662 else if ([systemFlavor caseInsensitiveCompare: NSPasteboardTypeTIFF] == NSOrderedSame)
663 {
664 dp = DataProviderPtr_t( new PNGDataProvider(systemData, NSBitmapImageFileTypeTIFF));
665 }
666 SAL_WNODEPRECATED_DECLARATIONS_PUSH
667 // "'NSFilenamesPboardType' is deprecated: first deprecated in macOS 10.14 - Create multiple
668 // pasteboard items with NSPasteboardTypeFileURL or kUTTypeFileURL instead"
669 else if ([systemFlavor caseInsensitiveCompare: NSFilenamesPboardType] == NSOrderedSame)
670 SAL_WNODEPRECATED_DECLARATIONS_POP
671 {
672 //dp = DataProviderPtr_t(new FileListDataProvider(systemData));
673 }
674 else
675 {
676 dp = DataProviderPtr_t(new ByteSequenceDataProvider(systemData));
677 }
678
679 return dp;
680 }
681
isValidMimeContentType(const OUString & contentType) const682 bool DataFlavorMapper::isValidMimeContentType(const OUString& contentType) const
683 {
684 bool result = true;
685
686 try
687 {
688 Reference<XMimeContentType> xCntType(mrXMimeCntFactory->createMimeContentType(contentType));
689 }
690 catch( const IllegalArgumentException& e )
691 {
692 SAL_WARN("vcl.osx.clipboard", "DataFlavorMapper::isValidMimeContentType(): Exception: " << e.Message);
693 result = false;
694 }
695
696 return result;
697 }
698
flavorSequenceToTypesArray(const css::uno::Sequence<css::datatransfer::DataFlavor> & flavors) const699 NSArray* DataFlavorMapper::flavorSequenceToTypesArray(const css::uno::Sequence<css::datatransfer::DataFlavor>& flavors) const
700 {
701 sal_uInt32 nFlavors = flavors.getLength();
702 NSMutableArray* array = [[NSMutableArray alloc] initWithCapacity: 1];
703
704 bool bNeedDummyInternalFlavor(false);
705
706 for (sal_uInt32 i = 0; i < nFlavors; i++)
707 {
708 if( flavors[i].MimeType.startsWith("image/bmp") )
709 {
710 [array addObject: NSPasteboardTypeTIFF];
711 }
712 else
713 {
714 const NSString* str = openOfficeToSystemFlavor(flavors[i], bNeedDummyInternalFlavor);
715
716 if (str != nullptr)
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 || bNeedDummyInternalFlavor)
728 {
729 [array addObject: [NSString stringWithUTF8String: FLAVOR_DUMMY_INTERNAL]];
730 }
731
732 return [array autorelease];
733 }
734
typesArrayToFlavorSequence(NSArray * types) const735 css::uno::Sequence<css::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
getAllSupportedPboardTypes()755 NSArray* DataFlavorMapper::getAllSupportedPboardTypes()
756 {
757 NSMutableArray* array = [[NSMutableArray alloc] initWithCapacity: SIZE_FLAVOR_MAP];
758
759 for (sal_uInt32 i = 0; i < SIZE_FLAVOR_MAP; i++)
760 {
761 if (flavorMap[i].SystemFlavor != nil)
762 [array addObject: flavorMap[i].SystemFlavor];
763 else
764 [array addObject: [NSString stringWithUTF8String: flavorMap[i].OOoFlavor]];
765 }
766
767 return [array autorelease];
768 }
769
770 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
771