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 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_vcl.hxx" 30 #include <sal/types.h> 31 32 #ifndef _TRANSFERABLE_HXX_ 33 #include "OSXTransferable.hxx" 34 #endif 35 36 #include "DataFlavorMapping.hxx" 37 38 using namespace rtl; 39 using namespace std; 40 using namespace osl; 41 using namespace cppu; 42 using namespace com::sun::star::uno; 43 using namespace com::sun::star::datatransfer; 44 using namespace com::sun::star::io; 45 using namespace com::sun::star::lang; 46 using namespace com::sun::star::container; 47 48 const Type CPPUTYPE_SEQINT8 = getCppuType((Sequence<sal_Int8>*)0); 49 const Type CPPUTYPE_OUSTRING = getCppuType((OUString*)0); 50 51 namespace // private 52 { 53 bool isValidFlavor( const DataFlavor& aFlavor ) 54 { 55 size_t len = aFlavor.MimeType.getLength(); 56 Type dtype = aFlavor.DataType; 57 return ((len > 0) && ((dtype == CPPUTYPE_SEQINT8) || (dtype == CPPUTYPE_OUSTRING))); 58 } 59 60 } // namespace private 61 62 63 OSXTransferable::OSXTransferable(const Reference<XMimeContentTypeFactory> rXMimeCntFactory, 64 DataFlavorMapperPtr_t pDataFlavorMapper, 65 NSPasteboard* pasteboard) : 66 mrXMimeCntFactory(rXMimeCntFactory), 67 mDataFlavorMapper(pDataFlavorMapper), 68 mPasteboard(pasteboard) 69 { 70 [mPasteboard retain]; 71 72 initClipboardItemList(); 73 } 74 75 76 OSXTransferable::~OSXTransferable() 77 { 78 [mPasteboard release]; 79 } 80 81 82 Any SAL_CALL OSXTransferable::getTransferData( const DataFlavor& aFlavor ) 83 throw( UnsupportedFlavorException, IOException, RuntimeException ) 84 { 85 if (!isValidFlavor(aFlavor) || !isDataFlavorSupported(aFlavor)) 86 { 87 throw UnsupportedFlavorException(OUString(RTL_CONSTASCII_USTRINGPARAM("AquaClipboard: Unsupported data flavor")), 88 static_cast<XTransferable*>(this)); 89 } 90 91 NSString* sysFormat = 92 (aFlavor.MimeType.compareToAscii( "image/bmp", 9 ) == 0) 93 ? mDataFlavorMapper->openOfficeImageToSystemFlavor( mPasteboard ) 94 : mDataFlavorMapper->openOfficeToSystemFlavor(aFlavor); 95 DataProviderPtr_t dp; 96 97 if ([sysFormat caseInsensitiveCompare: NSFilenamesPboardType] == NSOrderedSame) 98 { 99 NSArray* sysData = [mPasteboard propertyListForType: sysFormat]; 100 dp = mDataFlavorMapper->getDataProvider(sysFormat, sysData); 101 } 102 else 103 { 104 NSData* sysData = [mPasteboard dataForType: sysFormat]; 105 dp = mDataFlavorMapper->getDataProvider(sysFormat, sysData); 106 } 107 108 if (dp.get() == NULL) 109 { 110 throw UnsupportedFlavorException(OUString(RTL_CONSTASCII_USTRINGPARAM("AquaClipboard: Unsupported data flavor")), 111 static_cast<XTransferable*>(this)); 112 } 113 114 return dp->getOOoData(); 115 } 116 117 118 bool OSXTransferable::isUnicodeText(const DataFlavor& flavor) 119 { 120 return (flavor.DataType == CPPUTYPE_OUSTRING); 121 } 122 123 124 Sequence< DataFlavor > SAL_CALL OSXTransferable::getTransferDataFlavors( ) 125 throw( RuntimeException ) 126 { 127 return mFlavorList; 128 } 129 130 131 sal_Bool SAL_CALL OSXTransferable::isDataFlavorSupported(const DataFlavor& aFlavor) 132 throw( RuntimeException ) 133 { 134 for (sal_Int32 i = 0; i < mFlavorList.getLength(); i++) 135 if (compareDataFlavors(aFlavor, mFlavorList[i])) 136 return sal_True; 137 138 return sal_False; 139 } 140 141 142 void OSXTransferable::initClipboardItemList() 143 { 144 NSArray* pboardFormats = [mPasteboard types]; 145 146 if (pboardFormats == NULL) 147 { 148 throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM("AquaClipboard: Cannot get clipboard data")), 149 static_cast<XTransferable*>(this)); 150 } 151 152 mFlavorList = mDataFlavorMapper->typesArrayToFlavorSequence(pboardFormats); 153 } 154 155 156 /* Compares two DataFlavors. Returns true if both DataFlavor have the same media type 157 and the number of parameter and all parameter values do match otherwise false 158 is returned. 159 */ 160 bool OSXTransferable::compareDataFlavors(const DataFlavor& lhs, const DataFlavor& rhs ) 161 { 162 try 163 { 164 Reference<XMimeContentType> xLhs(mrXMimeCntFactory->createMimeContentType(lhs.MimeType)); 165 Reference<XMimeContentType> xRhs(mrXMimeCntFactory->createMimeContentType(rhs.MimeType)); 166 167 if (!xLhs->getFullMediaType().equalsIgnoreAsciiCase(xRhs->getFullMediaType()) || 168 !cmpAllContentTypeParameter(xLhs, xRhs)) 169 { 170 return false; 171 } 172 } 173 catch( IllegalArgumentException& ) 174 { 175 OSL_ENSURE( sal_False, "Invalid content type detected" ); 176 return false; 177 } 178 179 return true; 180 } 181 182 183 bool OSXTransferable::cmpAllContentTypeParameter(const Reference<XMimeContentType> xLhs, 184 const Reference<XMimeContentType> xRhs) const 185 { 186 Sequence<OUString> xLhsFlavors = xLhs->getParameters(); 187 Sequence<OUString> xRhsFlavors = xRhs->getParameters(); 188 189 // Stop here if the number of parameters is different already 190 if (xLhsFlavors.getLength() != xRhsFlavors.getLength()) 191 return false; 192 193 try 194 { 195 OUString pLhs; 196 OUString pRhs; 197 198 for (sal_Int32 i = 0; i < xLhsFlavors.getLength(); i++) 199 { 200 pLhs = xLhs->getParameterValue(xLhsFlavors[i]); 201 pRhs = xRhs->getParameterValue(xLhsFlavors[i]); 202 203 if (!pLhs.equalsIgnoreAsciiCase(pRhs)) 204 { 205 return false; 206 } 207 } 208 } 209 catch(IllegalArgumentException&) 210 { 211 return false; 212 } 213 214 return true; 215 } 216