| Index: Source/WebCore/platform/win/ClipboardWin.cpp
|
| diff --git a/Source/WebCore/platform/win/ClipboardWin.cpp b/Source/WebCore/platform/win/ClipboardWin.cpp
|
| deleted file mode 100644
|
| index 317b103c5b29a91385498eb75bf42d4618a5dfc0..0000000000000000000000000000000000000000
|
| --- a/Source/WebCore/platform/win/ClipboardWin.cpp
|
| +++ /dev/null
|
| @@ -1,814 +0,0 @@
|
| -/*
|
| - * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
|
| - *
|
| - * Redistribution and use in source and binary forms, with or without
|
| - * modification, are permitted provided that the following conditions
|
| - * are met:
|
| - * 1. Redistributions of source code must retain the above copyright
|
| - * notice, this list of conditions and the following disclaimer.
|
| - * 2. Redistributions in binary form must reproduce the above copyright
|
| - * notice, this list of conditions and the following disclaimer in the
|
| - * documentation and/or other materials provided with the distribution.
|
| - *
|
| - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
|
| - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
| - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
| - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
| - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
| - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
| - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
| - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
| - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| - */
|
| -
|
| -#include "config.h"
|
| -#include "ClipboardWin.h"
|
| -
|
| -#include "CachedImage.h"
|
| -#include "ClipboardUtilitiesWin.h"
|
| -#include "Document.h"
|
| -#include "DragData.h"
|
| -#include "Editor.h"
|
| -#include "Element.h"
|
| -#include "EventHandler.h"
|
| -#include "FileList.h"
|
| -#include "Frame.h"
|
| -#include "FrameLoader.h"
|
| -#include "FrameView.h"
|
| -#include "HTMLNames.h"
|
| -#include "HTMLParserIdioms.h"
|
| -#include "Image.h"
|
| -#include "MIMETypeRegistry.h"
|
| -#include "NotImplemented.h"
|
| -#include "Page.h"
|
| -#include "Pasteboard.h"
|
| -#include "PlatformMouseEvent.h"
|
| -#include "Range.h"
|
| -#include "RenderImage.h"
|
| -#include "ResourceResponse.h"
|
| -#include "SharedBuffer.h"
|
| -#include "WCDataObject.h"
|
| -#include "markup.h"
|
| -#include <shlwapi.h>
|
| -#include <wininet.h>
|
| -#include <wtf/RefPtr.h>
|
| -#include <wtf/text/CString.h>
|
| -#include <wtf/text/WTFString.h>
|
| -#include <wtf/text/StringHash.h>
|
| -
|
| -using namespace std;
|
| -
|
| -namespace WebCore {
|
| -
|
| -using namespace HTMLNames;
|
| -
|
| -// We provide the IE clipboard types (URL and Text), and the clipboard types specified in the WHATWG Web Applications 1.0 draft
|
| -// see http://www.whatwg.org/specs/web-apps/current-work/ Section 6.3.5.3
|
| -
|
| -enum ClipboardDataType { ClipboardDataTypeNone, ClipboardDataTypeURL, ClipboardDataTypeText, ClipboardDataTypeTextHTML };
|
| -
|
| -static ClipboardDataType clipboardTypeFromMIMEType(const String& type)
|
| -{
|
| - String qType = type.stripWhiteSpace().lower();
|
| -
|
| - // two special cases for IE compatibility
|
| - if (qType == "text" || qType == "text/plain" || qType.startsWith("text/plain;"))
|
| - return ClipboardDataTypeText;
|
| - if (qType == "url" || qType == "text/uri-list")
|
| - return ClipboardDataTypeURL;
|
| - if (qType == "text/html")
|
| - return ClipboardDataTypeTextHTML;
|
| -
|
| - return ClipboardDataTypeNone;
|
| -}
|
| -
|
| -#if !OS(WINCE)
|
| -static inline void pathRemoveBadFSCharacters(PWSTR psz, size_t length)
|
| -{
|
| - size_t writeTo = 0;
|
| - size_t readFrom = 0;
|
| - while (readFrom < length) {
|
| - UINT type = PathGetCharType(psz[readFrom]);
|
| - if (!psz[readFrom] || type & (GCT_LFNCHAR | GCT_SHORTCHAR))
|
| - psz[writeTo++] = psz[readFrom];
|
| -
|
| - readFrom++;
|
| - }
|
| - psz[writeTo] = 0;
|
| -}
|
| -#endif
|
| -
|
| -static String filesystemPathFromUrlOrTitle(const String& url, const String& title, const UChar* extension, bool isLink)
|
| -{
|
| -#if OS(WINCE)
|
| - notImplemented();
|
| - return String();
|
| -#else
|
| - static const size_t fsPathMaxLengthExcludingNullTerminator = MAX_PATH - 1;
|
| - bool usedURL = false;
|
| - WCHAR fsPathBuffer[MAX_PATH];
|
| - fsPathBuffer[0] = 0;
|
| - int extensionLen = extension ? lstrlen(extension) : 0;
|
| - int fsPathMaxLengthExcludingExtension = fsPathMaxLengthExcludingNullTerminator - extensionLen;
|
| -
|
| - if (!title.isEmpty()) {
|
| - size_t len = min<size_t>(title.length(), fsPathMaxLengthExcludingExtension);
|
| - CopyMemory(fsPathBuffer, title.characters(), len * sizeof(UChar));
|
| - fsPathBuffer[len] = 0;
|
| - pathRemoveBadFSCharacters(fsPathBuffer, len);
|
| - }
|
| -
|
| - if (!lstrlen(fsPathBuffer)) {
|
| - KURL kurl(ParsedURLString, url);
|
| - usedURL = true;
|
| - // The filename for any content based drag or file url should be the last element of
|
| - // the path. If we can't find it, or we're coming up with the name for a link
|
| - // we just use the entire url.
|
| - DWORD len = fsPathMaxLengthExcludingExtension;
|
| - String lastComponent = kurl.lastPathComponent();
|
| - if (kurl.isLocalFile() || (!isLink && !lastComponent.isEmpty())) {
|
| - len = min<DWORD>(fsPathMaxLengthExcludingExtension, lastComponent.length());
|
| - CopyMemory(fsPathBuffer, lastComponent.characters(), len * sizeof(UChar));
|
| - } else {
|
| - len = min<DWORD>(fsPathMaxLengthExcludingExtension, url.length());
|
| - CopyMemory(fsPathBuffer, url.characters(), len * sizeof(UChar));
|
| - }
|
| - fsPathBuffer[len] = 0;
|
| - pathRemoveBadFSCharacters(fsPathBuffer, len);
|
| - }
|
| -
|
| - if (!extension)
|
| - return String(static_cast<UChar*>(fsPathBuffer));
|
| -
|
| - if (!isLink && usedURL) {
|
| - PathRenameExtension(fsPathBuffer, extension);
|
| - return String(static_cast<UChar*>(fsPathBuffer));
|
| - }
|
| -
|
| - return makeString(static_cast<const UChar*>(fsPathBuffer), extension);
|
| -#endif
|
| -}
|
| -
|
| -static HGLOBAL createGlobalImageFileContent(SharedBuffer* data)
|
| -{
|
| - HGLOBAL memObj = GlobalAlloc(GPTR, data->size());
|
| - if (!memObj)
|
| - return 0;
|
| -
|
| - char* fileContents = (PSTR)GlobalLock(memObj);
|
| -
|
| - CopyMemory(fileContents, data->data(), data->size());
|
| -
|
| - GlobalUnlock(memObj);
|
| -
|
| - return memObj;
|
| -}
|
| -
|
| -static HGLOBAL createGlobalHDropContent(const KURL& url, String& fileName, SharedBuffer* data)
|
| -{
|
| - if (fileName.isEmpty() || !data)
|
| - return 0;
|
| -
|
| - WCHAR filePath[MAX_PATH];
|
| -
|
| - if (url.isLocalFile()) {
|
| - String localPath = decodeURLEscapeSequences(url.path());
|
| - // windows does not enjoy a leading slash on paths
|
| - if (localPath[0] == '/')
|
| - localPath = localPath.substring(1);
|
| - LPCWSTR localPathStr = localPath.charactersWithNullTermination();
|
| - if (wcslen(localPathStr) + 1 < MAX_PATH)
|
| - wcscpy_s(filePath, MAX_PATH, localPathStr);
|
| - else
|
| - return 0;
|
| - } else {
|
| -#if OS(WINCE)
|
| - notImplemented();
|
| - return 0;
|
| -#else
|
| - WCHAR tempPath[MAX_PATH];
|
| - WCHAR extension[MAX_PATH];
|
| - if (!::GetTempPath(WTF_ARRAY_LENGTH(tempPath), tempPath))
|
| - return 0;
|
| - if (!::PathAppend(tempPath, fileName.charactersWithNullTermination()))
|
| - return 0;
|
| - LPCWSTR foundExtension = ::PathFindExtension(tempPath);
|
| - if (foundExtension) {
|
| - if (wcscpy_s(extension, MAX_PATH, foundExtension))
|
| - return 0;
|
| - } else
|
| - *extension = 0;
|
| - ::PathRemoveExtension(tempPath);
|
| - for (int i = 1; i < 10000; i++) {
|
| - if (swprintf_s(filePath, MAX_PATH, TEXT("%s-%d%s"), tempPath, i, extension) == -1)
|
| - return 0;
|
| - if (!::PathFileExists(filePath))
|
| - break;
|
| - }
|
| - HANDLE tempFileHandle = CreateFile(filePath, GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
|
| - if (tempFileHandle == INVALID_HANDLE_VALUE)
|
| - return 0;
|
| -
|
| - // Write the data to this temp file.
|
| - DWORD written;
|
| - BOOL tempWriteSucceeded = WriteFile(tempFileHandle, data->data(), data->size(), &written, 0);
|
| - CloseHandle(tempFileHandle);
|
| - if (!tempWriteSucceeded)
|
| - return 0;
|
| -#endif
|
| - }
|
| -
|
| - SIZE_T dropFilesSize = sizeof(DROPFILES) + (sizeof(WCHAR) * (wcslen(filePath) + 2));
|
| - HGLOBAL memObj = GlobalAlloc(GHND | GMEM_SHARE, dropFilesSize);
|
| - if (!memObj)
|
| - return 0;
|
| -
|
| - DROPFILES* dropFiles = (DROPFILES*) GlobalLock(memObj);
|
| - dropFiles->pFiles = sizeof(DROPFILES);
|
| - dropFiles->fWide = TRUE;
|
| - wcscpy((LPWSTR)(dropFiles + 1), filePath);
|
| - GlobalUnlock(memObj);
|
| -
|
| - return memObj;
|
| -}
|
| -
|
| -static HGLOBAL createGlobalImageFileDescriptor(const String& url, const String& title, CachedImage* image)
|
| -{
|
| - ASSERT_ARG(image, image);
|
| - ASSERT(image->image()->data());
|
| -
|
| - HRESULT hr = S_OK;
|
| - HGLOBAL memObj = 0;
|
| - String fsPath;
|
| - memObj = GlobalAlloc(GPTR, sizeof(FILEGROUPDESCRIPTOR));
|
| - if (!memObj)
|
| - return 0;
|
| -
|
| - FILEGROUPDESCRIPTOR* fgd = (FILEGROUPDESCRIPTOR*)GlobalLock(memObj);
|
| - memset(fgd, 0, sizeof(FILEGROUPDESCRIPTOR));
|
| - fgd->cItems = 1;
|
| - fgd->fgd[0].dwFlags = FD_FILESIZE;
|
| - fgd->fgd[0].nFileSizeLow = image->image()->data()->size();
|
| -
|
| - const String& preferredTitle = title.isEmpty() ? image->response().suggestedFilename() : title;
|
| - String extension = image->image()->filenameExtension();
|
| - if (extension.isEmpty()) {
|
| - // Do not continue processing in the rare and unusual case where a decoded image is not able
|
| - // to provide a filename extension. Something tricky (like a bait-n-switch) is going on
|
| - return 0;
|
| - }
|
| - extension.insert(".", 0);
|
| - fsPath = filesystemPathFromUrlOrTitle(url, preferredTitle, extension.charactersWithNullTermination(), false);
|
| -
|
| - if (fsPath.length() <= 0) {
|
| - GlobalUnlock(memObj);
|
| - GlobalFree(memObj);
|
| - return 0;
|
| - }
|
| -
|
| - int maxSize = min(fsPath.length(), WTF_ARRAY_LENGTH(fgd->fgd[0].cFileName));
|
| - CopyMemory(fgd->fgd[0].cFileName, (LPCWSTR)fsPath.characters(), maxSize * sizeof(UChar));
|
| - GlobalUnlock(memObj);
|
| -
|
| - return memObj;
|
| -}
|
| -
|
| -
|
| -// writeFileToDataObject takes ownership of fileDescriptor and fileContent
|
| -static HRESULT writeFileToDataObject(IDataObject* dataObject, HGLOBAL fileDescriptor, HGLOBAL fileContent, HGLOBAL hDropContent)
|
| -{
|
| - HRESULT hr = S_OK;
|
| - FORMATETC* fe;
|
| - STGMEDIUM medium = {0};
|
| - medium.tymed = TYMED_HGLOBAL;
|
| -
|
| - if (!fileDescriptor || !fileContent)
|
| - goto exit;
|
| -
|
| - // Descriptor
|
| - fe = fileDescriptorFormat();
|
| -
|
| - medium.hGlobal = fileDescriptor;
|
| -
|
| - if (FAILED(hr = dataObject->SetData(fe, &medium, TRUE)))
|
| - goto exit;
|
| -
|
| - // Contents
|
| - fe = fileContentFormatZero();
|
| - medium.hGlobal = fileContent;
|
| - if (FAILED(hr = dataObject->SetData(fe, &medium, TRUE)))
|
| - goto exit;
|
| -
|
| -#if USE(CF)
|
| - // HDROP
|
| - if (hDropContent) {
|
| - medium.hGlobal = hDropContent;
|
| - hr = dataObject->SetData(cfHDropFormat(), &medium, TRUE);
|
| - }
|
| -#endif
|
| -
|
| -exit:
|
| - if (FAILED(hr)) {
|
| - if (fileDescriptor)
|
| - GlobalFree(fileDescriptor);
|
| - if (fileContent)
|
| - GlobalFree(fileContent);
|
| - if (hDropContent)
|
| - GlobalFree(hDropContent);
|
| - }
|
| - return hr;
|
| -}
|
| -
|
| -PassRefPtr<Clipboard> Clipboard::create(ClipboardAccessPolicy policy, DragData* dragData, Frame* frame)
|
| -{
|
| - if (dragData->platformData())
|
| - return ClipboardWin::create(DragAndDrop, dragData->platformData(), policy, frame);
|
| - return ClipboardWin::create(DragAndDrop, dragData->dragDataMap(), policy, frame);
|
| -}
|
| -
|
| -ClipboardWin::ClipboardWin(ClipboardType clipboardType, IDataObject* dataObject, ClipboardAccessPolicy policy, Frame* frame)
|
| - : Clipboard(policy, clipboardType)
|
| - , m_dataObject(dataObject)
|
| - , m_writableDataObject(0)
|
| - , m_frame(frame)
|
| -{
|
| -}
|
| -
|
| -ClipboardWin::ClipboardWin(ClipboardType clipboardType, WCDataObject* dataObject, ClipboardAccessPolicy policy, Frame* frame)
|
| - : Clipboard(policy, clipboardType)
|
| - , m_dataObject(dataObject)
|
| - , m_writableDataObject(dataObject)
|
| - , m_frame(frame)
|
| -{
|
| -}
|
| -
|
| -ClipboardWin::ClipboardWin(ClipboardType clipboardType, const DragDataMap& dataMap, ClipboardAccessPolicy policy, Frame* frame)
|
| - : Clipboard(policy, clipboardType)
|
| - , m_dataObject(0)
|
| - , m_writableDataObject(0)
|
| - , m_frame(frame)
|
| - , m_dragDataMap(dataMap)
|
| -{
|
| -}
|
| -
|
| -ClipboardWin::~ClipboardWin()
|
| -{
|
| - if (m_dragImage)
|
| - m_dragImage->removeClient(this);
|
| -}
|
| -
|
| -static bool writeURL(WCDataObject *data, const KURL& url, String title, bool withPlainText, bool withHTML)
|
| -{
|
| - ASSERT(data);
|
| -
|
| - if (url.isEmpty())
|
| - return false;
|
| -
|
| - if (title.isEmpty()) {
|
| - title = url.lastPathComponent();
|
| - if (title.isEmpty())
|
| - title = url.host();
|
| - }
|
| -
|
| - STGMEDIUM medium = {0};
|
| - medium.tymed = TYMED_HGLOBAL;
|
| -
|
| - medium.hGlobal = createGlobalData(url, title);
|
| - bool success = false;
|
| - if (medium.hGlobal && FAILED(data->SetData(urlWFormat(), &medium, TRUE)))
|
| - ::GlobalFree(medium.hGlobal);
|
| - else
|
| - success = true;
|
| -
|
| - if (withHTML) {
|
| - Vector<char> cfhtmlData;
|
| - markupToCFHTML(urlToMarkup(url, title), "", cfhtmlData);
|
| - medium.hGlobal = createGlobalData(cfhtmlData);
|
| - if (medium.hGlobal && FAILED(data->SetData(htmlFormat(), &medium, TRUE)))
|
| - ::GlobalFree(medium.hGlobal);
|
| - else
|
| - success = true;
|
| - }
|
| -
|
| - if (withPlainText) {
|
| - medium.hGlobal = createGlobalData(url.string());
|
| - if (medium.hGlobal && FAILED(data->SetData(plainTextWFormat(), &medium, TRUE)))
|
| - ::GlobalFree(medium.hGlobal);
|
| - else
|
| - success = true;
|
| - }
|
| -
|
| - return success;
|
| -}
|
| -
|
| -void ClipboardWin::clearData(const String& type)
|
| -{
|
| - // FIXME: Need to be able to write to the system clipboard <rdar://problem/5015941>
|
| - ASSERT(isForDragAndDrop());
|
| - if (!canWriteData() || !m_writableDataObject)
|
| - return;
|
| -
|
| - ClipboardDataType dataType = clipboardTypeFromMIMEType(type);
|
| -
|
| - if (dataType == ClipboardDataTypeURL) {
|
| - m_writableDataObject->clearData(urlWFormat()->cfFormat);
|
| - m_writableDataObject->clearData(urlFormat()->cfFormat);
|
| - }
|
| - if (dataType == ClipboardDataTypeText) {
|
| - m_writableDataObject->clearData(plainTextFormat()->cfFormat);
|
| - m_writableDataObject->clearData(plainTextWFormat()->cfFormat);
|
| - }
|
| -
|
| -}
|
| -
|
| -void ClipboardWin::clearAllData()
|
| -{
|
| - // FIXME: Need to be able to write to the system clipboard <rdar://problem/5015941>
|
| - ASSERT(isForDragAndDrop());
|
| - if (!canWriteData())
|
| - return;
|
| -
|
| - m_writableDataObject = 0;
|
| - WCDataObject::createInstance(&m_writableDataObject);
|
| - m_dataObject = m_writableDataObject;
|
| -}
|
| -
|
| -String ClipboardWin::getData(const String& type) const
|
| -{
|
| - if (!canReadData() || (!m_dataObject && m_dragDataMap.isEmpty()))
|
| - return "";
|
| -
|
| - ClipboardDataType dataType = clipboardTypeFromMIMEType(type);
|
| - if (dataType == ClipboardDataTypeText)
|
| - return m_dataObject ? getPlainText(m_dataObject.get()) : getPlainText(&m_dragDataMap);
|
| - if (dataType == ClipboardDataTypeURL)
|
| - return m_dataObject ? getURL(m_dataObject.get(), DragData::DoNotConvertFilenames) : getURL(&m_dragDataMap, DragData::DoNotConvertFilenames);
|
| - else if (dataType == ClipboardDataTypeTextHTML) {
|
| - String data = m_dataObject ? getTextHTML(m_dataObject.get()) : getTextHTML(&m_dragDataMap);
|
| - if (!data.isEmpty())
|
| - return data;
|
| - return m_dataObject ? getCFHTML(m_dataObject.get()) : getCFHTML(&m_dragDataMap);
|
| - }
|
| -
|
| - return "";
|
| -}
|
| -
|
| -bool ClipboardWin::setData(const String& type, const String& data)
|
| -{
|
| - // FIXME: Need to be able to write to the system clipboard <rdar://problem/5015941>
|
| - ASSERT(isForDragAndDrop());
|
| - if (!canWriteData() || !m_writableDataObject)
|
| - return false;
|
| -
|
| - ClipboardDataType winType = clipboardTypeFromMIMEType(type);
|
| -
|
| - if (winType == ClipboardDataTypeURL)
|
| - return WebCore::writeURL(m_writableDataObject.get(), KURL(ParsedURLString, data), String(), false, true);
|
| -
|
| - if (winType == ClipboardDataTypeText) {
|
| - STGMEDIUM medium = {0};
|
| - medium.tymed = TYMED_HGLOBAL;
|
| - medium.hGlobal = createGlobalData(data);
|
| - if (!medium.hGlobal)
|
| - return false;
|
| -
|
| - if (FAILED(m_writableDataObject->SetData(plainTextWFormat(), &medium, TRUE))) {
|
| - ::GlobalFree(medium.hGlobal);
|
| - return false;
|
| - }
|
| - return true;
|
| - }
|
| -
|
| - return false;
|
| -}
|
| -
|
| -static void addMimeTypesForFormat(ListHashSet<String>& results, const FORMATETC& format)
|
| -{
|
| - // URL and Text are provided for compatibility with IE's model
|
| - if (format.cfFormat == urlFormat()->cfFormat || format.cfFormat == urlWFormat()->cfFormat) {
|
| - results.add("URL");
|
| - results.add("text/uri-list");
|
| - }
|
| -
|
| - if (format.cfFormat == plainTextWFormat()->cfFormat || format.cfFormat == plainTextFormat()->cfFormat) {
|
| - results.add("Text");
|
| - results.add("text/plain");
|
| - }
|
| -}
|
| -
|
| -// extensions beyond IE's API
|
| -ListHashSet<String> ClipboardWin::types() const
|
| -{
|
| - ListHashSet<String> results;
|
| - if (!canReadTypes())
|
| - return results;
|
| -
|
| - if (!m_dataObject && m_dragDataMap.isEmpty())
|
| - return results;
|
| -
|
| - if (m_dataObject) {
|
| - COMPtr<IEnumFORMATETC> itr;
|
| -
|
| - if (FAILED(m_dataObject->EnumFormatEtc(DATADIR_GET, &itr)))
|
| - return results;
|
| -
|
| - if (!itr)
|
| - return results;
|
| -
|
| - FORMATETC data;
|
| -
|
| - // IEnumFORMATETC::Next returns S_FALSE if there are no more items.
|
| - while (itr->Next(1, &data, 0) == S_OK)
|
| - addMimeTypesForFormat(results, data);
|
| - } else {
|
| - for (DragDataMap::const_iterator it = m_dragDataMap.begin(); it != m_dragDataMap.end(); ++it) {
|
| - FORMATETC data;
|
| - data.cfFormat = (*it).key;
|
| - addMimeTypesForFormat(results, data);
|
| - }
|
| - }
|
| -
|
| - return results;
|
| -}
|
| -
|
| -PassRefPtr<FileList> ClipboardWin::files() const
|
| -{
|
| -#if OS(WINCE)
|
| - notImplemented();
|
| - return 0;
|
| -#else
|
| - RefPtr<FileList> files = FileList::create();
|
| - if (!canReadData())
|
| - return files.release();
|
| -
|
| - if (!m_dataObject && m_dragDataMap.isEmpty())
|
| - return files.release();
|
| -
|
| - if (m_dataObject) {
|
| - STGMEDIUM medium;
|
| - if (FAILED(m_dataObject->GetData(cfHDropFormat(), &medium)))
|
| - return files.release();
|
| -
|
| - HDROP hdrop = reinterpret_cast<HDROP>(GlobalLock(medium.hGlobal));
|
| - if (!hdrop)
|
| - return files.release();
|
| -
|
| - WCHAR filename[MAX_PATH];
|
| - UINT fileCount = DragQueryFileW(hdrop, 0xFFFFFFFF, 0, 0);
|
| - for (UINT i = 0; i < fileCount; i++) {
|
| - if (!DragQueryFileW(hdrop, i, filename, WTF_ARRAY_LENGTH(filename)))
|
| - continue;
|
| - files->append(File::create(reinterpret_cast<UChar*>(filename), File::AllContentTypes));
|
| - }
|
| -
|
| - GlobalUnlock(medium.hGlobal);
|
| - ReleaseStgMedium(&medium);
|
| - return files.release();
|
| - }
|
| - if (!m_dragDataMap.contains(cfHDropFormat()->cfFormat))
|
| - return files.release();
|
| - Vector<String> filesVector = m_dragDataMap.get(cfHDropFormat()->cfFormat);
|
| - for (Vector<String>::iterator it = filesVector.begin(); it != filesVector.end(); ++it)
|
| - files->append(File::create(*it));
|
| - return files.release();
|
| -#endif
|
| -}
|
| -
|
| -void ClipboardWin::setDragImage(CachedImage* image, Node *node, const IntPoint &loc)
|
| -{
|
| - if (!canSetDragImage())
|
| - return;
|
| -
|
| - if (m_dragImage)
|
| - m_dragImage->removeClient(this);
|
| - m_dragImage = image;
|
| - if (m_dragImage)
|
| - m_dragImage->addClient(this);
|
| -
|
| - m_dragLoc = loc;
|
| - m_dragImageElement = node;
|
| -}
|
| -
|
| -void ClipboardWin::setDragImage(CachedImage* img, const IntPoint &loc)
|
| -{
|
| - setDragImage(img, 0, loc);
|
| -}
|
| -
|
| -void ClipboardWin::setDragImageElement(Node *node, const IntPoint &loc)
|
| -{
|
| - setDragImage(0, node, loc);
|
| -}
|
| -
|
| -DragImageRef ClipboardWin::createDragImage(IntPoint& loc) const
|
| -{
|
| - HBITMAP result = 0;
|
| - if (m_dragImage) {
|
| - result = createDragImageFromImage(m_dragImage->image());
|
| - loc = m_dragLoc;
|
| - } else if (m_dragImageElement) {
|
| - Node* node = m_dragImageElement.get();
|
| - result = node->document()->frame()->nodeImage(node);
|
| - loc = m_dragLoc;
|
| - }
|
| - return result;
|
| -}
|
| -
|
| -static CachedImage* getCachedImage(Element* element)
|
| -{
|
| - // Attempt to pull CachedImage from element
|
| - ASSERT(element);
|
| - RenderObject* renderer = element->renderer();
|
| - if (!renderer || !renderer->isImage())
|
| - return 0;
|
| -
|
| - RenderImage* image = toRenderImage(renderer);
|
| - if (image->cachedImage() && !image->cachedImage()->errorOccurred())
|
| - return image->cachedImage();
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -static void writeImageToDataObject(IDataObject* dataObject, Element* element, const KURL& url)
|
| -{
|
| - // Shove image data into a DataObject for use as a file
|
| - CachedImage* cachedImage = getCachedImage(element);
|
| - if (!cachedImage || !cachedImage->imageForRenderer(element->renderer()) || !cachedImage->isLoaded())
|
| - return;
|
| -
|
| - SharedBuffer* imageBuffer = cachedImage->imageForRenderer(element->renderer())->data();
|
| - if (!imageBuffer || !imageBuffer->size())
|
| - return;
|
| -
|
| - HGLOBAL imageFileDescriptor = createGlobalImageFileDescriptor(url.string(), element->getAttribute(altAttr), cachedImage);
|
| - if (!imageFileDescriptor)
|
| - return;
|
| -
|
| - HGLOBAL imageFileContent = createGlobalImageFileContent(imageBuffer);
|
| - if (!imageFileContent) {
|
| - GlobalFree(imageFileDescriptor);
|
| - return;
|
| - }
|
| -
|
| - String fileName = cachedImage->response().suggestedFilename();
|
| - HGLOBAL hDropContent = createGlobalHDropContent(url, fileName, imageBuffer);
|
| - if (!hDropContent) {
|
| - GlobalFree(hDropContent);
|
| - return;
|
| - }
|
| -
|
| - writeFileToDataObject(dataObject, imageFileDescriptor, imageFileContent, hDropContent);
|
| -}
|
| -
|
| -void ClipboardWin::declareAndWriteDragImage(Element* element, const KURL& url, const String& title, Frame* frame)
|
| -{
|
| - // Order is important here for Explorer's sake
|
| - if (!m_writableDataObject)
|
| - return;
|
| - WebCore::writeURL(m_writableDataObject.get(), url, title, true, false);
|
| -
|
| - writeImageToDataObject(m_writableDataObject.get(), element, url);
|
| -
|
| - AtomicString imageURL = element->getAttribute(srcAttr);
|
| - if (imageURL.isEmpty())
|
| - return;
|
| -
|
| - KURL fullURL = frame->document()->completeURL(stripLeadingAndTrailingHTMLSpaces(imageURL));
|
| - if (fullURL.isEmpty())
|
| - return;
|
| - STGMEDIUM medium = {0};
|
| - medium.tymed = TYMED_HGLOBAL;
|
| -
|
| - // Put img tag on the clipboard referencing the image
|
| - Vector<char> data;
|
| - markupToCFHTML(createMarkup(element, IncludeNode, 0, ResolveAllURLs), "", data);
|
| - medium.hGlobal = createGlobalData(data);
|
| - if (medium.hGlobal && FAILED(m_writableDataObject->SetData(htmlFormat(), &medium, TRUE)))
|
| - ::GlobalFree(medium.hGlobal);
|
| -}
|
| -
|
| -void ClipboardWin::writeURL(const KURL& kurl, const String& titleStr, Frame*)
|
| -{
|
| - if (!m_writableDataObject)
|
| - return;
|
| - WebCore::writeURL(m_writableDataObject.get(), kurl, titleStr, true, true);
|
| -
|
| - String url = kurl.string();
|
| - ASSERT(url.containsOnlyASCII()); // KURL::string() is URL encoded.
|
| -
|
| - String fsPath = filesystemPathFromUrlOrTitle(url, titleStr, L".URL", true);
|
| - String contentString("[InternetShortcut]\r\nURL=" + url + "\r\n");
|
| - CString content = contentString.latin1();
|
| -
|
| - if (fsPath.length() <= 0)
|
| - return;
|
| -
|
| - HGLOBAL urlFileDescriptor = GlobalAlloc(GPTR, sizeof(FILEGROUPDESCRIPTOR));
|
| - if (!urlFileDescriptor)
|
| - return;
|
| -
|
| - HGLOBAL urlFileContent = GlobalAlloc(GPTR, content.length());
|
| - if (!urlFileContent) {
|
| - GlobalFree(urlFileDescriptor);
|
| - return;
|
| - }
|
| -
|
| - FILEGROUPDESCRIPTOR* fgd = static_cast<FILEGROUPDESCRIPTOR*>(GlobalLock(urlFileDescriptor));
|
| - ZeroMemory(fgd, sizeof(FILEGROUPDESCRIPTOR));
|
| - fgd->cItems = 1;
|
| - fgd->fgd[0].dwFlags = FD_FILESIZE;
|
| - fgd->fgd[0].nFileSizeLow = content.length();
|
| -
|
| - unsigned maxSize = min(fsPath.length(), WTF_ARRAY_LENGTH(fgd->fgd[0].cFileName));
|
| - CopyMemory(fgd->fgd[0].cFileName, fsPath.characters(), maxSize * sizeof(UChar));
|
| - GlobalUnlock(urlFileDescriptor);
|
| -
|
| - char* fileContents = static_cast<char*>(GlobalLock(urlFileContent));
|
| - CopyMemory(fileContents, content.data(), content.length());
|
| - GlobalUnlock(urlFileContent);
|
| -
|
| - writeFileToDataObject(m_writableDataObject.get(), urlFileDescriptor, urlFileContent, 0);
|
| -}
|
| -
|
| -void ClipboardWin::writeRange(Range* selectedRange, Frame* frame)
|
| -{
|
| - ASSERT(selectedRange);
|
| - if (!m_writableDataObject)
|
| - return;
|
| -
|
| - STGMEDIUM medium = {0};
|
| - medium.tymed = TYMED_HGLOBAL;
|
| -
|
| - Vector<char> data;
|
| - markupToCFHTML(createMarkup(selectedRange, 0, AnnotateForInterchange),
|
| - selectedRange->startContainer()->document()->url().string(), data);
|
| - medium.hGlobal = createGlobalData(data);
|
| - if (medium.hGlobal && FAILED(m_writableDataObject->SetData(htmlFormat(), &medium, TRUE)))
|
| - ::GlobalFree(medium.hGlobal);
|
| -
|
| - String str = frame->editor()->selectedTextForClipboard();
|
| - replaceNewlinesWithWindowsStyleNewlines(str);
|
| - replaceNBSPWithSpace(str);
|
| - medium.hGlobal = createGlobalData(str);
|
| - if (medium.hGlobal && FAILED(m_writableDataObject->SetData(plainTextWFormat(), &medium, TRUE)))
|
| - ::GlobalFree(medium.hGlobal);
|
| -
|
| - medium.hGlobal = 0;
|
| - if (frame->editor()->canSmartCopyOrDelete())
|
| - m_writableDataObject->SetData(smartPasteFormat(), &medium, TRUE);
|
| -}
|
| -
|
| -void ClipboardWin::writePlainText(const String& text)
|
| -{
|
| - if (!m_writableDataObject)
|
| - return;
|
| -
|
| - STGMEDIUM medium = {0};
|
| - medium.tymed = TYMED_HGLOBAL;
|
| -
|
| - String str = text;
|
| - replaceNewlinesWithWindowsStyleNewlines(str);
|
| - replaceNBSPWithSpace(str);
|
| - medium.hGlobal = createGlobalData(str);
|
| - if (medium.hGlobal && FAILED(m_writableDataObject->SetData(plainTextWFormat(), &medium, TRUE)))
|
| - ::GlobalFree(medium.hGlobal);
|
| -
|
| - medium.hGlobal = 0;
|
| -}
|
| -
|
| -bool ClipboardWin::hasData()
|
| -{
|
| - if (!m_dataObject && m_dragDataMap.isEmpty())
|
| - return false;
|
| -
|
| - if (m_dataObject) {
|
| - COMPtr<IEnumFORMATETC> itr;
|
| - if (FAILED(m_dataObject->EnumFormatEtc(DATADIR_GET, &itr)))
|
| - return false;
|
| -
|
| - if (!itr)
|
| - return false;
|
| -
|
| - FORMATETC data;
|
| -
|
| - // IEnumFORMATETC::Next returns S_FALSE if there are no more items.
|
| - if (itr->Next(1, &data, 0) == S_OK) {
|
| - // There is at least one item in the IDataObject
|
| - return true;
|
| - }
|
| -
|
| - return false;
|
| - }
|
| - return !m_dragDataMap.isEmpty();
|
| -}
|
| -
|
| -void ClipboardWin::setExternalDataObject(IDataObject *dataObject)
|
| -{
|
| - ASSERT(isForDragAndDrop());
|
| -
|
| - m_writableDataObject = 0;
|
| - m_dataObject = dataObject;
|
| -}
|
| -
|
| -} // namespace WebCore
|
|
|