diff options
Diffstat (limited to '')
-rw-r--r-- | vcl/ios/DataFlavorMapping.cxx | 571 | ||||
-rw-r--r-- | vcl/ios/DataFlavorMapping.hxx | 127 | ||||
-rw-r--r-- | vcl/ios/HtmlFmtFlt.cxx | 172 | ||||
-rw-r--r-- | vcl/ios/HtmlFmtFlt.hxx | 41 | ||||
-rw-r--r-- | vcl/ios/clipboard.cxx | 185 | ||||
-rw-r--r-- | vcl/ios/clipboard.hxx | 111 | ||||
-rw-r--r-- | vcl/ios/dummies.cxx | 138 | ||||
-rw-r--r-- | vcl/ios/iOSTransferable.cxx | 186 | ||||
-rw-r--r-- | vcl/ios/iOSTransferable.hxx | 73 | ||||
-rw-r--r-- | vcl/ios/iosinst.cxx | 197 |
10 files changed, 1801 insertions, 0 deletions
diff --git a/vcl/ios/DataFlavorMapping.cxx b/vcl/ios/DataFlavorMapping.cxx new file mode 100644 index 000000000..88b0e6199 --- /dev/null +++ b/vcl/ios/DataFlavorMapping.cxx @@ -0,0 +1,571 @@ +/* -*- Mode: ObjC; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include "DataFlavorMapping.hxx" +#include "HtmlFmtFlt.hxx" +#include <com/sun/star/datatransfer/UnsupportedFlavorException.hpp> +#include <com/sun/star/datatransfer/XMimeContentType.hpp> +#include <com/sun/star/datatransfer/MimeContentTypeFactory.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/uno/Sequence.hxx> +#include <comphelper/processfactory.hxx> + +#include <rtl/ustring.hxx> +#include <sal/log.hxx> +#include <osl/endian.h> + +#include <cassert> +#include <cstring> + +#include <premac.h> +#include <UIKit/UIKit.h> +#include <MobileCoreServices/MobileCoreServices.h> +#include <postmac.h> + +using namespace css::datatransfer; +using namespace css::uno; +using namespace css::lang; +using namespace cppu; + +namespace +{ +/* Determine whether or not a DataFlavor is valid. + */ +bool isValidFlavor(const DataFlavor& aFlavor) +{ + size_t len = aFlavor.MimeType.getLength(); + Type dtype = aFlavor.DataType; + return ((len > 0) + && ((dtype == cppu::UnoType<Sequence<sal_Int8>>::get()) + || (dtype == cppu::UnoType<OUString>::get()))); +} + +OUString NSStringToOUString(const NSString* cfString) +{ + assert(cfString && "Invalid parameter"); + + const char* utf8Str = [cfString UTF8String]; + unsigned int len = rtl_str_getLength(utf8Str); + + return OUString(utf8Str, len, RTL_TEXTENCODING_UTF8); +} + +NSString* OUStringToNSString(const OUString& ustring) +{ + OString utf8Str = OUStringToOString(ustring, RTL_TEXTENCODING_UTF8); + return [NSString stringWithCString:utf8Str.getStr() encoding:NSUTF8StringEncoding]; +} + +NSString* PBTYPE_PLAINTEXT = (__bridge NSString*)kUTTypePlainText; +// Nope. See commented-out use below. +// NSString* PBTYPE_UTF8PLAINTEXT = (__bridge NSString*)kUTTypeUTF8PlainText; +NSString* PBTYPE_RTF = (__bridge NSString*)kUTTypeRTF; +NSString* PBTYPE_PNG = (__bridge NSString*)kUTTypePNG; +NSString* PBTYPE_JPEG = (__bridge NSString*)kUTTypeJPEG; +NSString* PBTYPE_HTML = (__bridge NSString*)kUTTypeHTML; +NSString* PBTYPE_PDF = (__bridge NSString*)kUTTypePDF; +NSString* PBTYPE_SESX + = @"application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\""; +NSString* PBTYPE_SLSDX = @"application/" + @"x-openoffice-linksrcdescriptor-xml;windows_formatname=\"Star Link " + @"Source Descriptor (XML)\""; +NSString* PBTYPE_LSX + = @"application/x-openoffice-link-source-xml;windows_formatname=\"Star Link Source (XML)\""; +NSString* PBTYPE_EOX = @"application/x-openoffice-embedded-obj-xml;windows_formatname=\"Star " + @"Embedded Object (XML)\""; +NSString* PBTYPE_SVXB + = @"application/x-openoffice-svbx;windows_formatname=\"SVXB (StarView Bitmap/Animation)\""; +NSString* PBTYPE_GDIMF = @"application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\""; +NSString* PBTYPE_SODX = @"application/x-openoffice-objectdescriptor-xml;windows_formatname=\"Star " + @"Object Descriptor (XML)\""; +NSString* PBTYPE_DUMMY_INTERNAL = @"application/x-openoffice-internal"; + +const char* FLAVOR_SESX + = "application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\""; +const char* FLAVOR_SLSDX = "application/" + "x-openoffice-linksrcdescriptor-xml;windows_formatname=\"Star Link " + "Source Descriptor (XML)\""; +const char* FLAVOR_LSX + = "application/x-openoffice-link-source-xml;windows_formatname=\"Star Link Source (XML)\""; +const char* FLAVOR_EOX + = "application/x-openoffice-embedded-obj-xml;windows_formatname=\"Star Embedded Object (XML)\""; +const char* FLAVOR_SVXB + = "application/x-openoffice-svbx;windows_formatname=\"SVXB (StarView Bitmap/Animation)\""; +const char* FLAVOR_GDIMF + = "application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\""; +const char* FLAVOR_SODX = "application/x-openoffice-objectdescriptor-xml;windows_formatname=\"Star " + "Object Descriptor (XML)\""; +const char* FLAVOR_DUMMY_INTERNAL = "application/x-openoffice-internal"; + +struct FlavorMap +{ + NSString* SystemFlavor; + const char* OOoFlavor; + const char* HumanPresentableName; + bool DataTypeOUString; // sequence<byte> otherwise +}; + +static const FlavorMap flavorMap[] + = { { PBTYPE_PLAINTEXT, "text/plain;charset=utf-16", "Unicode Text (UTF-16)", true }, + // Nope. The LO code does not understand text/plain in UTF-8. Which is a shame. + // PBTYPE_UTF8PLAINTEXT, "text/plain;charset=utf-8", "Unicode Text (UTF-8)", false }, + { PBTYPE_RTF, "text/rtf", "Rich Text Format", false }, + { PBTYPE_PNG, "image/png", "Portable Network Graphics", false }, + { PBTYPE_JPEG, "image/jpeg", "JPEG", false }, + { PBTYPE_HTML, "text/html", "Plain HTML", false }, + { PBTYPE_PDF, "application/pdf", "PDF File", false }, + { PBTYPE_SESX, FLAVOR_SESX, "Star Embed Source (XML)", false }, + { PBTYPE_SLSDX, FLAVOR_SLSDX, "Star Link Source Descriptor (XML)", false }, + { PBTYPE_LSX, FLAVOR_LSX, "Star Link Source (XML)", false }, + { PBTYPE_EOX, FLAVOR_EOX, "Star Embedded Object (XML)", false }, + { PBTYPE_SVXB, FLAVOR_SVXB, "SVXB (StarView Bitmap/Animation", false }, + { PBTYPE_GDIMF, FLAVOR_GDIMF, "GDIMetaFile", false }, + { PBTYPE_SODX, FLAVOR_SODX, "Star Object Descriptor (XML)", false }, + { PBTYPE_DUMMY_INTERNAL, FLAVOR_DUMMY_INTERNAL, "internal data", false } }; + +#define SIZE_FLAVOR_MAP (sizeof(flavorMap) / sizeof(FlavorMap)) + +inline bool isByteSequenceType(const Type& theType) +{ + return (theType == cppu::UnoType<Sequence<sal_Int8>>::get()); +} + +inline bool isOUStringType(const Type& theType) +{ + return (theType == cppu::UnoType<OUString>::get()); +} + +} // unnamed namespace + +/* A base class for other data provider. + */ +class DataProviderBaseImpl : public DataProvider +{ +public: + DataProviderBaseImpl(const Any& data); + DataProviderBaseImpl(id data); + virtual ~DataProviderBaseImpl() override; + +protected: + Any mData; + //NSData* mSystemData; + id mSystemData; +}; + +DataProviderBaseImpl::DataProviderBaseImpl(const Any& data) + : mData(data) + , mSystemData(nil) +{ +} + +DataProviderBaseImpl::DataProviderBaseImpl(id data) + : mSystemData(data) +{ + [mSystemData retain]; +} + +DataProviderBaseImpl::~DataProviderBaseImpl() +{ + if (mSystemData) + { + [mSystemData release]; + } +} + +class UniDataProvider : public DataProviderBaseImpl +{ +public: + UniDataProvider(const Any& data); + UniDataProvider(NSData* data); + + NSData* getSystemData() override; + Any getOOoData() override; +}; + +UniDataProvider::UniDataProvider(const Any& data) + : DataProviderBaseImpl(data) +{ +} + +UniDataProvider::UniDataProvider(NSData* data) + : DataProviderBaseImpl(data) +{ +} + +NSData* UniDataProvider::getSystemData() +{ + OUString ustr; + mData >>= ustr; + + OString strUtf8; + ustr.convertToString(&strUtf8, RTL_TEXTENCODING_UTF8, OUSTRING_TO_OSTRING_CVTFLAGS); + + return [NSData dataWithBytes:strUtf8.getStr() length:strUtf8.getLength()]; +} + +Any UniDataProvider::getOOoData() +{ + Any oOOData; + + if (mSystemData) + { + oOOData <<= OUString(static_cast<const char*>([mSystemData bytes]), [mSystemData length], + RTL_TEXTENCODING_UTF8); + } + else + { + oOOData = mData; + } + + return oOOData; +} + +class ByteSequenceDataProvider : public DataProviderBaseImpl +{ +public: + ByteSequenceDataProvider(const Any& data); + ByteSequenceDataProvider(NSData* data); + + NSData* getSystemData() override; + Any getOOoData() override; +}; + +ByteSequenceDataProvider::ByteSequenceDataProvider(const Any& data) + : DataProviderBaseImpl(data) +{ +} + +ByteSequenceDataProvider::ByteSequenceDataProvider(NSData* data) + : DataProviderBaseImpl(data) +{ +} + +NSData* ByteSequenceDataProvider::getSystemData() +{ + Sequence<sal_Int8> rawData; + mData >>= rawData; + + return [NSData dataWithBytes:rawData.getArray() length:rawData.getLength()]; +} + +Any ByteSequenceDataProvider::getOOoData() +{ + Any oOOData; + + if (mSystemData) + { + unsigned int flavorDataLength = [mSystemData length]; + Sequence<sal_Int8> byteSequence; + byteSequence.realloc(flavorDataLength); + memcpy(byteSequence.getArray(), [mSystemData bytes], flavorDataLength); + oOOData <<= byteSequence; + } + else + { + oOOData = mData; + } + + return oOOData; +} + +class HTMLFormatDataProvider : public DataProviderBaseImpl +{ +public: + HTMLFormatDataProvider(NSData* data); + + NSData* getSystemData() override; + Any getOOoData() override; +}; + +HTMLFormatDataProvider::HTMLFormatDataProvider(NSData* data) + : DataProviderBaseImpl(data) +{ +} + +NSData* HTMLFormatDataProvider::getSystemData() +{ + Sequence<sal_Int8> textHtmlData; + mData >>= textHtmlData; + + Sequence<sal_Int8> htmlFormatData = TextHtmlToHTMLFormat(textHtmlData); + + return [NSData dataWithBytes:htmlFormatData.getArray() length:htmlFormatData.getLength()]; +} + +Any HTMLFormatDataProvider::getOOoData() +{ + Any oOOData; + + if (mSystemData) + { + unsigned int flavorDataLength = [mSystemData length]; + Sequence<sal_Int8> unkHtmlData; + + unkHtmlData.realloc(flavorDataLength); + memcpy(unkHtmlData.getArray(), [mSystemData bytes], flavorDataLength); + + Sequence<sal_Int8>* pPlainHtml = &unkHtmlData; + Sequence<sal_Int8> plainHtml; + + if (isHTMLFormat(unkHtmlData)) + { + plainHtml = HTMLFormatToTextHtml(unkHtmlData); + pPlainHtml = &plainHtml; + } + + oOOData <<= *pPlainHtml; + } + else + { + oOOData = mData; + } + + return oOOData; +} + +DataFlavorMapper::DataFlavorMapper() +{ + Reference<XComponentContext> xContext = comphelper::getProcessComponentContext(); + mrXMimeCntFactory = MimeContentTypeFactory::create(xContext); +} + +DataFlavorMapper::~DataFlavorMapper() +{ + // release potential NSStrings + for (OfficeOnlyTypes::iterator it = maOfficeOnlyTypes.begin(); it != maOfficeOnlyTypes.end(); + ++it) + { + [it->second release]; + it->second = nil; + } +} + +DataFlavor DataFlavorMapper::systemToOpenOfficeFlavor(const NSString* systemDataFlavor) const +{ + DataFlavor oOOFlavor; + + for (size_t i = 0; i < SIZE_FLAVOR_MAP; i++) + { + if ([systemDataFlavor + caseInsensitiveCompare:const_cast<NSString*>(flavorMap[i].SystemFlavor)] + == NSOrderedSame) + { + oOOFlavor.MimeType = OUString::createFromAscii(flavorMap[i].OOoFlavor); + oOOFlavor.HumanPresentableName + = OUString::createFromAscii(flavorMap[i].HumanPresentableName); + oOOFlavor.DataType = flavorMap[i].DataTypeOUString + ? cppu::UnoType<OUString>::get() + : cppu::UnoType<Sequence<sal_Int8>>::get(); + return oOOFlavor; + } + } // for + + // look if this might be an internal type; if it comes in here it must have + // been through openOfficeToSystemFlavor before, so it should then be in the map + OUString aTryFlavor(NSStringToOUString(systemDataFlavor)); + if (maOfficeOnlyTypes.find(aTryFlavor) != maOfficeOnlyTypes.end()) + { + oOOFlavor.MimeType = aTryFlavor; + oOOFlavor.HumanPresentableName.clear(); + oOOFlavor.DataType = cppu::UnoType<Sequence<sal_Int8>>::get(); + } + + return oOOFlavor; +} + +NSString* DataFlavorMapper::openOfficeToSystemFlavor(const DataFlavor& oOOFlavor, + bool& rbInternal) const +{ + NSString* sysFlavor = nullptr; + rbInternal = false; + + for (size_t i = 0; i < SIZE_FLAVOR_MAP; ++i) + { + if (oOOFlavor.MimeType.startsWith(OUString::createFromAscii(flavorMap[i].OOoFlavor))) + { + sysFlavor = flavorMap[i].SystemFlavor; + } + } + + if (!sysFlavor) + { + // For some reason, if we allow text/html, we get an OSL_ENSURE failure in xmloff that + // apparently is a symptom of something being seriously wrong: + // xmloff/source/transform/OOo2Oasis.cxx:1925: duplicate doc handler + // Because is then followed a bit later by an assertion failure: + // Assertion failed: (!m_pFirst && !m_pLast && "There are still indices registered"), function ~SwIndexReg, file [...]/sw/source/core/bastyp/index.cxx, line 226 + + if (oOOFlavor.MimeType == "text/html") + return nil; + + rbInternal = true; + OfficeOnlyTypes::const_iterator it = maOfficeOnlyTypes.find(oOOFlavor.MimeType); + + if (it == maOfficeOnlyTypes.end()) + sysFlavor = maOfficeOnlyTypes[oOOFlavor.MimeType] + = OUStringToNSString(oOOFlavor.MimeType); + else + sysFlavor = it->second; + } + + return sysFlavor; +} + +NSString* DataFlavorMapper::openOfficeImageToSystemFlavor(UIPasteboard* pPasteboard) +{ + if ([pPasteboard containsPasteboardTypes:@[ PBTYPE_PNG ]]) + return PBTYPE_PNG; + else if ([pPasteboard containsPasteboardTypes:@[ PBTYPE_JPEG ]]) + return PBTYPE_JPEG; + else if ([pPasteboard containsPasteboardTypes:@[ PBTYPE_PDF ]]) + return PBTYPE_PDF; + return @""; +} + +DataProviderPtr_t +DataFlavorMapper::getDataProvider(const NSString* systemFlavor, + Reference<XTransferable> const& rTransferable) const +{ + DataProviderPtr_t dp; + + try + { + DataFlavor oOOFlavor = systemToOpenOfficeFlavor(systemFlavor); + + Any data = rTransferable->getTransferData(oOOFlavor); + + if (isByteSequenceType(data.getValueType())) + { + dp = DataProviderPtr_t(new ByteSequenceDataProvider(data)); + } + else // Must be OUString type + { + SAL_WARN_IF(!isOUStringType(data.getValueType()), "vcl", "must be OUString type"); + dp = DataProviderPtr_t(new UniDataProvider(data)); + } + } + catch (UnsupportedFlavorException&) + { + // Somebody violates the contract of the clipboard + // interface @see XTransferable + } + + return dp; +} + +DataProviderPtr_t DataFlavorMapper::getDataProvider(const NSString* systemFlavor, + NSData* systemData) +{ + DataProviderPtr_t dp; + + if ([systemFlavor caseInsensitiveCompare:PBTYPE_PLAINTEXT] == NSOrderedSame) + { + dp = DataProviderPtr_t(new UniDataProvider(systemData)); + } + else if ([systemFlavor caseInsensitiveCompare:PBTYPE_HTML] == NSOrderedSame) + { + dp = DataProviderPtr_t(new HTMLFormatDataProvider(systemData)); + } + else + { + dp = DataProviderPtr_t(new ByteSequenceDataProvider(systemData)); + } + + return dp; +} + +bool DataFlavorMapper::isValidMimeContentType(const OUString& contentType) const +{ + bool result = true; + + try + { + Reference<XMimeContentType> xCntType(mrXMimeCntFactory->createMimeContentType(contentType)); + } + catch (IllegalArgumentException&) + { + result = false; + } + + return result; +} + +NSArray* DataFlavorMapper::flavorSequenceToTypesArray( + const css::uno::Sequence<css::datatransfer::DataFlavor>& flavors) const +{ + const sal_uInt32 nFlavors = flavors.getLength(); + NSMutableArray* array = [[NSMutableArray alloc] initWithCapacity:1]; + + bool bNeedDummyInternalFlavor(false); + + for (sal_uInt32 i = 0; i < nFlavors; i++) + { + if (flavors[i].MimeType.startsWith("image/bmp")) + { + [array addObject:PBTYPE_PNG]; + } + else + { + const NSString* str = openOfficeToSystemFlavor(flavors[i], bNeedDummyInternalFlavor); + + if (str != nil) + { + [str retain]; + [array addObject:str]; + } + } + } + + // #i89462# #i90747# + // in case no system flavor was found to report + // report at least one so D&D between OOo targets works + if ([array count] == 0 || bNeedDummyInternalFlavor) + { + [array addObject:PBTYPE_DUMMY_INTERNAL]; + } + + return [array autorelease]; +} + +css::uno::Sequence<css::datatransfer::DataFlavor> +DataFlavorMapper::typesArrayToFlavorSequence(NSArray* types) const +{ + int nFormats = [types count]; + Sequence<DataFlavor> flavors; + + for (int i = 0; i < nFormats; i++) + { + NSString* sysFormat = [types objectAtIndex:i]; + DataFlavor oOOFlavor = systemToOpenOfficeFlavor(sysFormat); + + if (isValidFlavor(oOOFlavor)) + { + flavors.realloc(flavors.getLength() + 1); + flavors[flavors.getLength() - 1] = oOOFlavor; + SAL_INFO("vcl.ios.clipboard", + "Mapped " << [sysFormat UTF8String] << " to " << oOOFlavor.MimeType); + } + } + + return flavors; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/ios/DataFlavorMapping.hxx b/vcl/ios/DataFlavorMapping.hxx new file mode 100644 index 000000000..7e527dc09 --- /dev/null +++ b/vcl/ios/DataFlavorMapping.hxx @@ -0,0 +1,127 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_IOS_DATAFLAVORMAPPING_HXX +#define INCLUDED_VCL_IOS_DATAFLAVORMAPPING_HXX + +#include <com/sun/star/datatransfer/DataFlavor.hpp> +#include <com/sun/star/datatransfer/XMimeContentTypeFactory.hpp> +#include <com/sun/star/datatransfer/XTransferable.hpp> +#include <com/sun/star/lang/XMultiComponentFactory.hpp> + +#include <premac.h> +#import <UIKit/UIKit.h> +#include <postmac.h> + +#include <memory> +#include <unordered_map> + +/* An interface to get the clipboard data in either + system or OOo format. + */ +class DataProvider +{ +public: + virtual ~DataProvider(){}; + + /* Get the clipboard data in the system format. + The caller has to retain/release the returned + CFDataRef on demand. + */ + virtual NSData* getSystemData() = 0; + + /* Get the clipboard data in OOo format. + */ + virtual css::uno::Any getOOoData() = 0; +}; + +typedef std::unique_ptr<DataProvider> DataProviderPtr_t; + +class DataFlavorMapper +{ +public: + /* Initialize a DataFavorMapper instance. Throws a RuntimeException in case the XMimeContentTypeFactory service + cannot be created. + */ + DataFlavorMapper(); + ~DataFlavorMapper(); + + /* Map a system data flavor to an OpenOffice data flavor. + Return an empty string if there is not suitable + mapping from a system data flavor to an OpenOffice data + flavor. + */ + css::datatransfer::DataFlavor systemToOpenOfficeFlavor(const NSString* systemDataFlavor) const; + + /* Map an OpenOffice data flavor to a system data flavor. + If there is no suitable mapping available NULL will + be returned. + */ + NSString* openOfficeToSystemFlavor(const css::datatransfer::DataFlavor& oooDataFlavor, + bool& rbInternal) const; + + /* Select the best available image data type + If there is no suitable mapping available NULL will + be returned. + */ + static NSString* openOfficeImageToSystemFlavor(UIPasteboard* pPasteboard); + + /* Get a data provider which is able to provide the data 'rTransferable' offers in a format that can + be put on to the system clipboard. + */ + DataProviderPtr_t getDataProvider( + const NSString* systemFlavor, + const css::uno::Reference<css::datatransfer::XTransferable>& rTransferable) const; + + /* Get a data provider which is able to provide 'systemData' in the OOo expected format. + */ + static DataProviderPtr_t getDataProvider(const NSString* systemFlavor, NSArray* systemData); + + /* Get a data provider which is able to provide 'systemData' in the OOo expected format. + */ + static DataProviderPtr_t getDataProvider(const NSString* systemFlavor, NSData* systemData); + + /* Translate a sequence of DataFlavors into a NSArray of system types. + Only those DataFlavors for which a suitable mapping to a system + type exist will be contained in the returned types array. + */ + NSArray* flavorSequenceToTypesArray( + const css::uno::Sequence<css::datatransfer::DataFlavor>& flavors) const; + + /* Translate a NSArray of system types into a sequence of DataFlavors. + Only those types for which a suitable mapping to a DataFlavor + exist will be contained in the new DataFlavor Sequence. + */ + css::uno::Sequence<css::datatransfer::DataFlavor> + typesArrayToFlavorSequence(NSArray* types) const; + +private: + /* Determines if the provided Mime content type is valid. + */ + bool isValidMimeContentType(const OUString& contentType) const; + +private: + css::uno::Reference<css::datatransfer::XMimeContentTypeFactory> mrXMimeCntFactory; + typedef std::unordered_map<OUString, NSString*> OfficeOnlyTypes; + mutable OfficeOnlyTypes maOfficeOnlyTypes; +}; + +#endif // INCLUDED_VCL_IOS_DATAFLAVORMAPPING_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/ios/HtmlFmtFlt.cxx b/vcl/ios/HtmlFmtFlt.cxx new file mode 100644 index 000000000..4f90ced3b --- /dev/null +++ b/vcl/ios/HtmlFmtFlt.cxx @@ -0,0 +1,172 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "HtmlFmtFlt.hxx" + +#include <rtl/string.h> +#include <osl/diagnose.h> + +#include <string> +#include <sstream> +#include <vector> +#include <iomanip> +#include <cassert> + +using namespace com::sun::star::uno; + +// converts the openoffice text/html clipboard format to the HTML Format +// well known under MS Windows +// the MS HTML Format has a header before the real html data + +// Version:1.0 Version number of the clipboard. Starting is 0.9 +// StartHTML: Byte count from the beginning of the clipboard to the start +// of the context, or -1 if no context +// EndHTML: Byte count from the beginning of the clipboard to the end +// of the context, or -1 if no context +// StartFragment: Byte count from the beginning of the clipboard to the +// start of the fragment +// EndFragment: Byte count from the beginning of the clipboard to the +// end of the fragment +// StartSelection: Byte count from the beginning of the clipboard to the +// start of the selection +// EndSelection: Byte count from the beginning of the clipboard to the +// end of the selection + +// StartSelection and EndSelection are optional +// The fragment should be preceded and followed by the HTML comments +// <!--StartFragment--> and <!--EndFragment--> (no space between !-- and the +// text + +namespace +{ +std::string GetHtmlFormatHeader(size_t startHtml, size_t endHtml, size_t startFragment, + size_t endFragment) +{ + std::ostringstream htmlHeader; + htmlHeader << "Version:1.0" << '\r' << '\n'; + htmlHeader << "StartHTML:" << std::setw(10) << std::setfill('0') << std::dec << startHtml + << '\r' << '\n'; + htmlHeader << "EndHTML:" << std::setw(10) << std::setfill('0') << std::dec << endHtml << '\r' + << '\n'; + htmlHeader << "StartFragment:" << std::setw(10) << std::setfill('0') << std::dec + << startFragment << '\r' << '\n'; + htmlHeader << "EndFragment:" << std::setw(10) << std::setfill('0') << std::dec << endFragment + << '\r' << '\n'; + return htmlHeader.str(); +} +} + +// the office always writes the start and end html tag in upper cases and +// without spaces both tags don't allow parameters +const std::string TAG_HTML = std::string("<html>"); +const std::string TAG_END_HTML = std::string("</html>"); + +// The body tag may have parameters so we need to search for the +// closing '>' manually e.g. <BODY param> #92840# +const std::string TAG_BODY = std::string("<body"); +const std::string TAG_END_BODY = std::string("</body"); + +Sequence<sal_Int8> SAL_CALL TextHtmlToHTMLFormat(Sequence<sal_Int8> const& aTextHtml) +{ + OSL_ASSERT(aTextHtml.getLength() > 0); + + if (aTextHtml.getLength() <= 0) + return Sequence<sal_Int8>(); + + // fill the buffer with dummy values to calc the exact length + std::string dummyHtmlHeader = GetHtmlFormatHeader(0, 0, 0, 0); + size_t lHtmlFormatHeader = dummyHtmlHeader.length(); + + std::string textHtml(reinterpret_cast<const char*>(aTextHtml.getConstArray()), + reinterpret_cast<const char*>(aTextHtml.getConstArray()) + + aTextHtml.getLength()); + + std::string::size_type nStartHtml = textHtml.find(TAG_HTML) + lHtmlFormatHeader + - 1; // we start one before '<HTML>' Word 2000 does also so + std::string::size_type nEndHtml = textHtml.find(TAG_END_HTML) + lHtmlFormatHeader + + TAG_END_HTML.length() + + 1; // our SOffice 5.2 wants 2 behind </HTML>? + + // The body tag may have parameters so we need to search for the + // closing '>' manually e.g. <BODY param> #92840# + std::string::size_type nStartFragment + = textHtml.find(">", textHtml.find(TAG_BODY)) + lHtmlFormatHeader + 1; + std::string::size_type nEndFragment = textHtml.find(TAG_END_BODY) + lHtmlFormatHeader; + + std::string htmlFormat + = GetHtmlFormatHeader(nStartHtml, nEndHtml, nStartFragment, nEndFragment); + htmlFormat += textHtml; + + Sequence<sal_Int8> byteSequence(htmlFormat.length() + 1); // space the trailing '\0' + memset(byteSequence.getArray(), 0, byteSequence.getLength()); + + memcpy(static_cast<void*>(byteSequence.getArray()), + static_cast<const void*>(htmlFormat.c_str()), htmlFormat.length()); + + return byteSequence; +} + +const char* const HtmlStartTag = "<html"; + +Sequence<sal_Int8> HTMLFormatToTextHtml(const Sequence<sal_Int8>& aHTMLFormat) +{ + assert(isHTMLFormat(aHTMLFormat) && "No HTML Format provided"); + + Sequence<sal_Int8>& nonconstHTMLFormatRef = const_cast<Sequence<sal_Int8>&>(aHTMLFormat); + char* dataStart = reinterpret_cast<char*>(nonconstHTMLFormatRef.getArray()); + char* dataEnd = dataStart + nonconstHTMLFormatRef.getLength() - 1; + const char* htmlStartTag = strcasestr(dataStart, HtmlStartTag); + + assert(htmlStartTag && "Seems to be no HTML at all"); + + // It doesn't seem to be HTML? Well then simply return what has been + // provided in non-debug builds + if (htmlStartTag == nullptr) + { + return aHTMLFormat; + } + + sal_Int32 len = dataEnd - htmlStartTag; + Sequence<sal_Int8> plainHtmlData(len); + + memcpy(static_cast<void*>(plainHtmlData.getArray()), htmlStartTag, len); + + return plainHtmlData; +} + +/* A simple format detection. We are just comparing the first few bytes + of the provided byte sequence to see whether or not it is the MS + Office Html format. If it shows that this is not reliable enough we + can improve this +*/ +const char HtmlFormatStart[] = "Version:"; +int const HtmlFormatStartLen = (sizeof(HtmlFormatStart) - 1); + +bool isHTMLFormat(const Sequence<sal_Int8>& aHtmlSequence) +{ + if (aHtmlSequence.getLength() < HtmlFormatStartLen) + return false; + + return rtl_str_compareIgnoreAsciiCase_WithLength( + HtmlFormatStart, HtmlFormatStartLen, + reinterpret_cast<const char*>(aHtmlSequence.getConstArray()), HtmlFormatStartLen) + == 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/ios/HtmlFmtFlt.hxx b/vcl/ios/HtmlFmtFlt.hxx new file mode 100644 index 000000000..b11b19857 --- /dev/null +++ b/vcl/ios/HtmlFmtFlt.hxx @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_OSX_HTMLFMTFLT_HXX +#define INCLUDED_VCL_OSX_HTMLFMTFLT_HXX + +#include <com/sun/star/uno/Sequence.hxx> + +/* Transform plain HTML into the format expected by MS Office. + */ +css::uno::Sequence<sal_Int8> TextHtmlToHTMLFormat(css::uno::Sequence<sal_Int8> const& aTextHtml); + +/* Transform the MS Office HTML format into plain HTML. + */ +css::uno::Sequence<sal_Int8> HTMLFormatToTextHtml(const css::uno::Sequence<sal_Int8>& aHTMLFormat); + +/* Detects whether the given byte sequence contains the MS Office Html format. + + @returns True if the MS Office Html format will be detected False otherwise. + */ +bool isHTMLFormat(const css::uno::Sequence<sal_Int8>& aHtmlSequence); + +#endif // INCLUDED_VCL_OSX_HTMLFMTFLT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/ios/clipboard.cxx b/vcl/ios/clipboard.cxx new file mode 100644 index 000000000..b60cda1be --- /dev/null +++ b/vcl/ios/clipboard.cxx @@ -0,0 +1,185 @@ +/* -*- Mode: ObjC; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "ios/iosinst.hxx" + +#include "clipboard.hxx" + +#include "DataFlavorMapping.hxx" +#include "iOSTransferable.hxx" +#include <com/sun/star/datatransfer/MimeContentTypeFactory.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <comphelper/processfactory.hxx> +#include <cppuhelper/supportsservice.hxx> + +iOSClipboard::iOSClipboard() + : WeakComponentImplHelper<XSystemClipboard, XServiceInfo>(m_aMutex) +{ + auto xContext = comphelper::getProcessComponentContext(); + + mrXMimeCntFactory = css::datatransfer::MimeContentTypeFactory::create(xContext); + + mpDataFlavorMapper.reset(new DataFlavorMapper()); + + mPasteboard = [UIPasteboard generalPasteboard]; + assert(mPasteboard != nil); +} + +iOSClipboard::~iOSClipboard() {} + +css::uno::Reference<css::datatransfer::XTransferable> SAL_CALL iOSClipboard::getContents() +{ + osl::MutexGuard aGuard(m_aMutex); + + return css::uno::Reference<css::datatransfer::XTransferable>( + new iOSTransferable(mrXMimeCntFactory, mpDataFlavorMapper, mPasteboard)); +} + +void SAL_CALL iOSClipboard::setContents( + const css::uno::Reference<css::datatransfer::XTransferable>& xTransferable, + const css::uno::Reference<css::datatransfer::clipboard::XClipboardOwner>& /*xClipboardOwner*/) +{ + NSArray* types = xTransferable.is() ? mpDataFlavorMapper->flavorSequenceToTypesArray( + xTransferable->getTransferDataFlavors()) + : [NSArray array]; + + osl::ClearableMutexGuard aGuard(m_aMutex); + + NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithCapacity:1]; + NSArray* array = @[ dict ]; + + for (sal_uInt32 i = 0; i < [types count]; ++i) + { + DataProviderPtr_t dp = mpDataFlavorMapper->getDataProvider(types[i], xTransferable); + + if (dp.get() != nullptr) + { + NSData* pBoardData = (NSData*)dp->getSystemData(); + dict[types[i]] = pBoardData; + } + } + [mPasteboard setItems:array options:@{}]; + + // We don't keep a copy of the clipboard contents around in-process, so fire the lost clipboard + // ownership event right away. + // fireLostClipboardOwnershipEvent(xClipboardOwner, xTransferable); + + // fireClipboardChangedEvent(xTransferable); +} + +OUString SAL_CALL iOSClipboard::getName() { return OUString(); } + +sal_Int8 SAL_CALL iOSClipboard::getRenderingCapabilities() { return 0; } + +void SAL_CALL iOSClipboard::addClipboardListener( + const css::uno::Reference<css::datatransfer::clipboard::XClipboardListener>& listener) +{ + osl::MutexGuard aGuard(m_aMutex); + + if (!listener.is()) + throw css::lang::IllegalArgumentException( + "empty reference", static_cast<css::datatransfer::clipboard::XClipboardEx*>(this), 1); + + mClipboardListeners.push_back(listener); +} + +void SAL_CALL iOSClipboard::removeClipboardListener( + const css::uno::Reference<css::datatransfer::clipboard::XClipboardListener>& listener) +{ + osl::MutexGuard aGuard(m_aMutex); + + if (!listener.is()) + throw css::lang::IllegalArgumentException( + "empty reference", static_cast<css::datatransfer::clipboard::XClipboardEx*>(this), 1); + + mClipboardListeners.remove(listener); +} + +void iOSClipboard::fireClipboardChangedEvent( + css::uno::Reference<css::datatransfer::XTransferable> xNewContents) +{ + osl::ClearableMutexGuard aGuard(m_aMutex); + + std::list<css::uno::Reference<css::datatransfer::clipboard::XClipboardListener>> listeners( + mClipboardListeners); + css::datatransfer::clipboard::ClipboardEvent aEvent; + + if (!listeners.empty()) + { + aEvent = css::datatransfer::clipboard::ClipboardEvent(static_cast<OWeakObject*>(this), + xNewContents); + } + + aGuard.clear(); + + while (!listeners.empty()) + { + if (listeners.front().is()) + { + try + { + listeners.front()->changedContents(aEvent); + } + catch (const css::uno::RuntimeException&) + { + } + } + listeners.pop_front(); + } +} + +void iOSClipboard::fireLostClipboardOwnershipEvent( + css::uno::Reference<css::datatransfer::clipboard::XClipboardOwner> const& oldOwner, + css::uno::Reference<css::datatransfer::XTransferable> const& oldContent) +{ + assert(oldOwner.is()); + + try + { + oldOwner->lostOwnership(static_cast<css::datatransfer::clipboard::XClipboardEx*>(this), + oldContent); + } + catch (const css::uno::RuntimeException&) + { + } +} + +OUString SAL_CALL iOSClipboard::getImplementationName() +{ + return OUString("com.sun.star.datatransfer.clipboard.iOSClipboard"); +} + +sal_Bool SAL_CALL iOSClipboard::supportsService(const OUString& ServiceName) +{ + return cppu::supportsService(this, ServiceName); +} + +css::uno::Sequence<OUString> SAL_CALL iOSClipboard::getSupportedServiceNames() +{ + return { OUString("com.sun.star.datatransfer.clipboard.SystemClipboard") }; +} + +css::uno::Reference<css::uno::XInterface> +IosSalInstance::CreateClipboard(const css::uno::Sequence<css::uno::Any>&) +{ + return css::uno::Reference<css::uno::XInterface>( + static_cast<cppu::OWeakObject*>(new iOSClipboard())); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/ios/clipboard.hxx b/vcl/ios/clipboard.hxx new file mode 100644 index 000000000..144e9c3ac --- /dev/null +++ b/vcl/ios/clipboard.hxx @@ -0,0 +1,111 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_IOS_CLIPBOARD_HXX +#define INCLUDED_VCL_IOS_CLIPBOARD_HXX + +#include "DataFlavorMapping.hxx" +#include <rtl/ustring.hxx> +#include <sal/types.h> +#include <cppuhelper/compbase.hxx> +#include <com/sun/star/datatransfer/XTransferable.hpp> +#include <com/sun/star/datatransfer/clipboard/XClipboardEx.hpp> +#include <com/sun/star/datatransfer/clipboard/XClipboardOwner.hpp> +#include <com/sun/star/datatransfer/clipboard/XClipboardListener.hpp> +#include <com/sun/star/datatransfer/clipboard/XClipboardNotifier.hpp> +#include <com/sun/star/datatransfer/clipboard/XSystemClipboard.hpp> +#include <com/sun/star/datatransfer/XMimeContentTypeFactory.hpp> +#include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <cppuhelper/basemutex.hxx> +#include <com/sun/star/lang/XMultiComponentFactory.hpp> + +#include <list> + +#include <premac.h> +#import <UIKit/UIKit.h> +#include <postmac.h> + +class iOSClipboard + : public ::cppu::BaseMutex, + public ::cppu::WeakComponentImplHelper<css::datatransfer::clipboard::XSystemClipboard, + css::lang::XServiceInfo> +{ +public: + iOSClipboard(); + + virtual ~iOSClipboard() override; + iOSClipboard(const iOSClipboard&) = delete; + iOSClipboard& operator=(const iOSClipboard&) = delete; + + // XClipboard + + css::uno::Reference<css::datatransfer::XTransferable> SAL_CALL getContents() override; + + void SAL_CALL setContents( + const css::uno::Reference<css::datatransfer::XTransferable>& xTransferable, + const css::uno::Reference<css::datatransfer::clipboard::XClipboardOwner>& xClipboardOwner) + override; + + OUString SAL_CALL getName() override; + + // XClipboardEx + + sal_Int8 SAL_CALL getRenderingCapabilities() override; + + // XClipboardNotifier + + void SAL_CALL addClipboardListener( + const css::uno::Reference<css::datatransfer::clipboard::XClipboardListener>& listener) + override; + + void SAL_CALL removeClipboardListener( + const css::uno::Reference<css::datatransfer::clipboard::XClipboardListener>& listener) + override; + + // XServiceInfo + + OUString SAL_CALL getImplementationName() override; + + sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override; + + css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; + +private: + /* Notify the current clipboard owner that he is no longer the clipboard owner. */ + void fireLostClipboardOwnershipEvent( + css::uno::Reference<css::datatransfer::clipboard::XClipboardOwner> const& oldOwner, + css::uno::Reference<css::datatransfer::XTransferable> const& oldContent); + + /* Notify all registered XClipboardListener that the clipboard content has changed. */ + void + fireClipboardChangedEvent(css::uno::Reference<css::datatransfer::XTransferable> xNewContents); + +private: + css::uno::Reference<css::datatransfer::XMimeContentTypeFactory> mrXMimeCntFactory; + std::list<css::uno::Reference<css::datatransfer::clipboard::XClipboardListener>> + mClipboardListeners; + css::uno::Reference<css::datatransfer::clipboard::XClipboardOwner> mXClipboardOwner; + std::shared_ptr<DataFlavorMapper> mpDataFlavorMapper; + UIPasteboard* mPasteboard; +}; + +#endif // INCLUDED_VCL_IOS_CLIPBOARD_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/ios/dummies.cxx b/vcl/ios/dummies.cxx new file mode 100644 index 000000000..d62609dc9 --- /dev/null +++ b/vcl/ios/dummies.cxx @@ -0,0 +1,138 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#include <vcl/svapp.hxx> +#include "salprn.hxx" +#include "quartz/salgdi.h" +#include "headless/svpinst.hxx" +#include "unx/fontmanager.hxx" +#include "unx/gendata.hxx" + +class FreetypeManager +{ +}; + +std::unique_ptr<SalPrinter> SvpSalInstance::CreatePrinter( SalInfoPrinter* /* pInfoPrinter */ ) +{ + return nullptr; +} + +OUString SvpSalInstance::GetDefaultPrinter() +{ + return OUString(); +} + +std::unique_ptr<GenPspGraphics> SvpSalInstance::CreatePrintGraphics() +{ + return nullptr; +} + +void SvpSalInstance::PostPrintersChanged() +{ +} + +SalInfoPrinter* SvpSalInstance::CreateInfoPrinter( SalPrinterQueueInfo* /* pQueueInfo */, + ImplJobSetup* /* pJobSetup */ ) +{ + return NULL; +} + +void SvpSalInstance::DestroyInfoPrinter( SalInfoPrinter* pPrinter ) +{ + delete pPrinter; +} + +void SvpSalInstance::GetPrinterQueueInfo( ImplPrnQueueList* /* pList */ ) +{ +} + +void SvpSalInstance::GetPrinterQueueState( SalPrinterQueueInfo* /* pInfo */ ) +{ +} + +std::unique_ptr<SalPrinter> SalGenericInstance::CreatePrinter( SalInfoPrinter* /* pInfoPrinter */ ) +{ + return nullptr; +} + +OUString SalGenericInstance::GetDefaultPrinter() +{ + return OUString(); +} + +void SalGenericInstance::PostPrintersChanged() +{ +} + +SalInfoPrinter* SalGenericInstance::CreateInfoPrinter( SalPrinterQueueInfo* /* pQueueInfo */, + ImplJobSetup* /* pJobSetup */ ) +{ + return NULL; +} + +void SalGenericInstance::DestroyInfoPrinter( SalInfoPrinter* pPrinter ) +{ + delete pPrinter; +} + +void SalGenericInstance::GetPrinterQueueInfo( ImplPrnQueueList* /* pList */ ) +{ +} + +void SalGenericInstance::GetPrinterQueueState( SalPrinterQueueInfo* /* pInfo */ ) +{ +} + +void SalGenericInstance::updatePrinterUpdate() +{ +} + +void SalGenericInstance::jobStartedPrinterUpdate() +{ +} + +void SalGenericInstance::jobEndedPrinterUpdate() +{ +} + +bool AquaSalGraphics::drawEPS( long, long, long, long, void*, sal_uInt32 ) +{ + return false; +} + +using namespace psp; + +GenericUnixSalData::GenericUnixSalData(GenericUnixSalDataType const t, SalInstance *const pInstance) + : m_eType(t) + , m_pDisplay(nullptr) + , m_pFreetypeManager(new FreetypeManager) + , m_pPrintFontManager(nullptr) +{ + m_pInstance = pInstance; + SetSalData(this); +} + +GenericUnixSalData::~GenericUnixSalData() +{ +} + +PrintFontManager::~PrintFontManager() +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/ios/iOSTransferable.cxx b/vcl/ios/iOSTransferable.cxx new file mode 100644 index 000000000..9ec27867f --- /dev/null +++ b/vcl/ios/iOSTransferable.cxx @@ -0,0 +1,186 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <com/sun/star/datatransfer/UnsupportedFlavorException.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <sal/log.hxx> +#include <sal/types.h> +#include <osl/diagnose.h> + +#include "iOSTransferable.hxx" + +#include "DataFlavorMapping.hxx" + +using namespace std; +using namespace osl; +using namespace cppu; +using namespace com::sun::star::uno; +using namespace com::sun::star::datatransfer; +using namespace com::sun::star::lang; + +namespace +{ +bool isValidFlavor(const DataFlavor& aFlavor) +{ + size_t len = aFlavor.MimeType.getLength(); + Type dtype = aFlavor.DataType; + return ((len > 0) + && ((dtype == cppu::UnoType<Sequence<sal_Int8>>::get()) + || (dtype == cppu::UnoType<OUString>::get()))); +} + +bool cmpAllContentTypeParameter(const Reference<XMimeContentType>& xLhs, + const Reference<XMimeContentType>& xRhs) +{ + Sequence<OUString> xLhsFlavors = xLhs->getParameters(); + Sequence<OUString> xRhsFlavors = xRhs->getParameters(); + + // Stop here if the number of parameters is different already + if (xLhsFlavors.getLength() != xRhsFlavors.getLength()) + return false; + + try + { + OUString pLhs; + OUString pRhs; + + for (sal_Int32 i = 0; i < xLhsFlavors.getLength(); i++) + { + pLhs = xLhs->getParameterValue(xLhsFlavors[i]); + pRhs = xRhs->getParameterValue(xLhsFlavors[i]); + + if (!pLhs.equalsIgnoreAsciiCase(pRhs)) + { + return false; + } + } + } + catch (IllegalArgumentException&) + { + return false; + } + + return true; +} + +} // unnamed namespace + +iOSTransferable::iOSTransferable(const Reference<XMimeContentTypeFactory>& rXMimeCntFactory, + std::shared_ptr<DataFlavorMapper> pDataFlavorMapper, + UIPasteboard* pasteboard) + : mrXMimeCntFactory(rXMimeCntFactory) + , mDataFlavorMapper(pDataFlavorMapper) + , mPasteboard(pasteboard) +{ + [mPasteboard retain]; + + initClipboardItemList(); +} + +iOSTransferable::~iOSTransferable() { [mPasteboard release]; } + +Any SAL_CALL iOSTransferable::getTransferData(const DataFlavor& aFlavor) +{ + if (!isValidFlavor(aFlavor) || !isDataFlavorSupported(aFlavor)) + { + throw UnsupportedFlavorException("Unsupported data flavor", + static_cast<XTransferable*>(this)); + } + + bool bInternal(false); + NSString* sysFormat = (aFlavor.MimeType.startsWith("image/png")) + ? DataFlavorMapper::openOfficeImageToSystemFlavor(mPasteboard) + : mDataFlavorMapper->openOfficeToSystemFlavor(aFlavor, bInternal); + DataProviderPtr_t dp; + + NSData* sysData = [mPasteboard dataForPasteboardType:sysFormat]; + dp = DataFlavorMapper::getDataProvider(sysFormat, sysData); + + if (dp.get() == nullptr) + { + throw UnsupportedFlavorException("Unsupported data flavor", + static_cast<XTransferable*>(this)); + } + + return dp->getOOoData(); +} + +Sequence<DataFlavor> SAL_CALL iOSTransferable::getTransferDataFlavors() { return mFlavorList; } + +sal_Bool SAL_CALL iOSTransferable::isDataFlavorSupported(const DataFlavor& aFlavor) +{ + for (sal_Int32 i = 0; i < mFlavorList.getLength(); i++) + if (compareDataFlavors(aFlavor, mFlavorList[i])) + return true; + + return false; +} + +void iOSTransferable::initClipboardItemList() +{ + NSArray* pboardFormats = [mPasteboard pasteboardTypes]; + + if (pboardFormats == nullptr) + { + throw RuntimeException("Cannot get clipboard data", static_cast<XTransferable*>(this)); + } + +#ifdef SAL_LOG_INFO + NSString* types = @""; + for (unsigned i = 0; i < [pboardFormats count]; i++) + { + if ([types length] > 0) + types = [types stringByAppendingString:@", "]; + types = [types stringByAppendingString:[pboardFormats objectAtIndex:i]]; + } + SAL_INFO("vcl.ios.clipboard", "Types on clipboard: " << [types UTF8String]); +#endif + + mFlavorList = mDataFlavorMapper->typesArrayToFlavorSequence(pboardFormats); +} + +/* Compares two DataFlavors. Returns true if both DataFlavor have the same media type + and the number of parameter and all parameter values do match otherwise false + is returned. + */ +bool iOSTransferable::compareDataFlavors(const DataFlavor& lhs, const DataFlavor& rhs) +{ + try + { + Reference<XMimeContentType> xLhs(mrXMimeCntFactory->createMimeContentType(lhs.MimeType)); + Reference<XMimeContentType> xRhs(mrXMimeCntFactory->createMimeContentType(rhs.MimeType)); + + if (!xLhs->getFullMediaType().equalsIgnoreAsciiCase(xRhs->getFullMediaType()) + || !cmpAllContentTypeParameter(xLhs, xRhs)) + { + return false; + } + } + catch (IllegalArgumentException&) + { + OSL_FAIL("Invalid content type detected"); + return false; + } + + return true; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/ios/iOSTransferable.hxx b/vcl/ios/iOSTransferable.hxx new file mode 100644 index 000000000..5c685dba8 --- /dev/null +++ b/vcl/ios/iOSTransferable.hxx @@ -0,0 +1,73 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_IOS_IOSTRANSFERABLE_HXX +#define INCLUDED_VCL_IOS_IOSTRANSFERABLE_HXX + +#include <com/sun/star/datatransfer/XTransferable.hpp> +#include <cppuhelper/implbase.hxx> +#include <com/sun/star/datatransfer/XMimeContentTypeFactory.hpp> +#include <com/sun/star/datatransfer/XMimeContentType.hpp> + +#include "DataFlavorMapping.hxx" + +#include <premac.h> +#import <UIKit/UIKit.h> +#include <postmac.h> + +#include <memory> +#include <vector> + +class iOSTransferable : public ::cppu::WeakImplHelper<css::datatransfer::XTransferable> +{ +public: + explicit iOSTransferable( + css::uno::Reference<css::datatransfer::XMimeContentTypeFactory> const& rXMimeCntFactory, + std::shared_ptr<DataFlavorMapper> pDataFlavorMapper, UIPasteboard* pasteboard); + + virtual ~iOSTransferable() override; + iOSTransferable(const iOSTransferable&) = delete; + iOSTransferable& operator=(const iOSTransferable&) = delete; + + // XTransferable + + virtual css::uno::Any SAL_CALL + getTransferData(const css::datatransfer::DataFlavor& aFlavor) override; + + css::uno::Sequence<css::datatransfer::DataFlavor> SAL_CALL getTransferDataFlavors() override; + + sal_Bool SAL_CALL isDataFlavorSupported(const css::datatransfer::DataFlavor& aFlavor) override; + + // Helper functions not part of the XTransferable interface + + void initClipboardItemList(); + + bool compareDataFlavors(const css::datatransfer::DataFlavor& lhs, + const css::datatransfer::DataFlavor& rhs); + +private: + css::uno::Sequence<css::datatransfer::DataFlavor> mFlavorList; + css::uno::Reference<css::datatransfer::XMimeContentTypeFactory> mrXMimeCntFactory; + std::shared_ptr<DataFlavorMapper> mDataFlavorMapper; + UIPasteboard* mPasteboard; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/ios/iosinst.cxx b/vcl/ios/iosinst.cxx new file mode 100644 index 000000000..65963ef9c --- /dev/null +++ b/vcl/ios/iosinst.cxx @@ -0,0 +1,197 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <premac.h> +#include <UIKit/UIKit.h> +#include <postmac.h> + +#include "ios/iosinst.hxx" +#include "headless/svpdummies.hxx" +#include "unx/gendata.hxx" +#include "quartz/utils.h" +#include <vcl/layout.hxx> +#include <vcl/settings.hxx> + +// Totally wrong of course but doesn't seem to harm much in the iOS app. +static int viewWidth = 1, viewHeight = 1; + +class IosSalData : public GenericUnixSalData +{ +public: + explicit IosSalData(SalInstance *pInstance) + : GenericUnixSalData(SAL_DATA_IOS, pInstance) + { + } + virtual void ErrorTrapPush() {} + virtual bool ErrorTrapPop( bool ) { return false; } +}; + +void IosSalInstance::GetWorkArea( tools::Rectangle& rRect ) +{ + rRect = tools::Rectangle( Point( 0, 0 ), + Size( viewWidth, viewHeight ) ); +} + +IosSalInstance *IosSalInstance::getInstance() +{ + if (!ImplGetSVData()) + return NULL; + IosSalData *pData = static_cast<IosSalData *>(ImplGetSVData()->mpSalData); + if (!pData) + return NULL; + return static_cast<IosSalInstance *>(pData->m_pInstance); +} + +IosSalInstance::IosSalInstance( std::unique_ptr<SalYieldMutex> pMutex ) + : SvpSalInstance( std::move(pMutex) ) +{ +} + +IosSalInstance::~IosSalInstance() +{ +} + +class IosSalSystem : public SvpSalSystem { +public: + IosSalSystem() : SvpSalSystem() {} + virtual ~IosSalSystem() {} + virtual int ShowNativeDialog( const OUString& rTitle, + const OUString& rMessage, + const std::vector< OUString >& rButtons ); +}; + +SalSystem *IosSalInstance::CreateSalSystem() +{ + return new IosSalSystem(); +} + +class IosSalFrame : public SvpSalFrame +{ +public: + IosSalFrame( IosSalInstance *pInstance, + SalFrame *pParent, + SalFrameStyleFlags nSalFrameStyle) + : SvpSalFrame( pInstance, pParent, nSalFrameStyle ) + { + if (pParent == NULL && viewWidth > 1 && viewHeight > 1) + SetPosSize(0, 0, viewWidth, viewHeight, SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT); + } + + virtual void GetWorkArea( tools::Rectangle& rRect ) override + { + IosSalInstance::getInstance()->GetWorkArea( rRect ); + } + + virtual void ShowFullScreen( bool, sal_Int32 ) override + { + SetPosSize( 0, 0, viewWidth, viewHeight, + SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT ); + } + + virtual void UpdateSettings( AllSettings &rSettings ) override + { + // Clobber the UI fonts + vcl::Font aFont( "Helvetica", Size( 0, 10 ) ); + + StyleSettings aStyleSet = rSettings.GetStyleSettings(); + aStyleSet.SetAppFont( aFont ); + aStyleSet.SetHelpFont( aFont ); + aStyleSet.SetMenuFont( aFont ); + aStyleSet.SetToolFont( aFont ); + aStyleSet.SetLabelFont( aFont ); + aStyleSet.SetRadioCheckFont( aFont ); + aStyleSet.SetPushButtonFont( aFont ); + aStyleSet.SetFieldFont( aFont ); + aStyleSet.SetIconFont( aFont ); + aStyleSet.SetTabFont( aFont ); + aStyleSet.SetGroupFont( aFont ); + + Color aBackgroundColor( 0xff, 0xff, 0xff ); + aStyleSet.BatchSetBackgrounds( aBackgroundColor, false ); + aStyleSet.SetMenuColor( aBackgroundColor ); + aStyleSet.SetMenuBarColor( aBackgroundColor ); + aStyleSet.SetDialogColor( aBackgroundColor ); + + rSettings.SetStyleSettings( aStyleSet ); + } +}; + +SalFrame *IosSalInstance::CreateChildFrame( SystemParentData* pParent, SalFrameStyleFlags nStyle ) +{ + pParent = NULL; + return new IosSalFrame( this, NULL, nStyle ); +} + +SalFrame *IosSalInstance::CreateFrame( SalFrame* pParent, SalFrameStyleFlags nStyle ) +{ + return new IosSalFrame( this, pParent, nStyle ); +} + +void SalAbort( const OUString& rErrorText, bool bDumpCore ) +{ + (void) bDumpCore; + + NSLog(@"SalAbort: %s", OUStringToOString(rErrorText, osl_getThreadTextEncoding()).getStr() ); +} + +const OUString& SalGetDesktopEnvironment() +{ + static OUString aEnv( "iOS" ); + return aEnv; +} + +SalData::SalData() : + m_pInstance( 0 ), + mpFontList( 0 ), + mxRGBSpace( CGColorSpaceCreateDeviceRGB() ), + mxGraySpace( CGColorSpaceCreateDeviceGray() ) +{ +} + +SalData::~SalData() +{ +} + +// This is our main entry point: +SalInstance *CreateSalInstance() +{ + IosSalInstance* pInstance = new IosSalInstance( std::make_unique<SvpSalYieldMutex>() ); + new IosSalData( pInstance ); + pInstance->AcquireYieldMutex(); + return pInstance; +} + +void DestroySalInstance( SalInstance *pInst ) +{ + pInst->ReleaseYieldMutexAll(); + delete pInst; +} + +int IosSalSystem::ShowNativeDialog( const OUString& rTitle, + const OUString& rMessage, + const std::vector< OUString >& rButtons ) +{ + (void)rButtons; + + NSLog(@"%@: %@", CreateNSString(rTitle), CreateNSString(rMessage)); + + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |