1/*
2 * Copyright (C) 2006 Zack Rusin <zack@kde.org>
3 * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
4 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "config.h"
29#include "Pasteboard.h"
30
31#include "DocumentFragment.h"
32#include "Editor.h"
33#include "Frame.h"
34#include "Image.h"
35#include "RenderImage.h"
36#include "markup.h"
37#include <qapplication.h>
38#include <qclipboard.h>
39#include <qdebug.h>
40#include <qmimedata.h>
41#include <qurl.h>
42
43#define methodDebug() qDebug() << "PasteboardQt: " << __FUNCTION__;
44
45namespace WebCore {
46
47Pasteboard::Pasteboard()
48    : m_selectionMode(false)
49{
50}
51
52Pasteboard* Pasteboard::generalPasteboard()
53{
54    static Pasteboard* pasteboard = 0;
55    if (!pasteboard)
56        pasteboard = new Pasteboard();
57    return pasteboard;
58}
59
60void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame)
61{
62    QMimeData* md = new QMimeData;
63    QString text = frame->editor()->selectedText();
64    text.replace(QChar(0xa0), QLatin1Char(' '));
65    md->setText(text);
66
67    QString markup = createMarkup(selectedRange, 0, AnnotateForInterchange, false, AbsoluteURLs);
68#ifdef Q_OS_MAC
69    markup.prepend(QLatin1String("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /></head><body>"));
70    markup.append(QLatin1String("</body></html>"));
71    md->setData(QLatin1String("text/html"), markup.toUtf8());
72#else
73    md->setHtml(markup);
74#endif
75
76#ifndef QT_NO_CLIPBOARD
77    QApplication::clipboard()->setMimeData(md, m_selectionMode ? QClipboard::Selection : QClipboard::Clipboard);
78#endif
79    if (canSmartCopyOrDelete)
80        md->setData(QLatin1String("application/vnd.qtwebkit.smartpaste"), QByteArray());
81}
82
83bool Pasteboard::canSmartReplace()
84{
85#ifndef QT_NO_CLIPBOARD
86    if (QApplication::clipboard()->mimeData()->hasFormat((QLatin1String("application/vnd.qtwebkit.smartpaste"))))
87        return true;
88#endif
89    return false;
90}
91
92String Pasteboard::plainText(Frame*)
93{
94#ifndef QT_NO_CLIPBOARD
95    return QApplication::clipboard()->text(m_selectionMode ? QClipboard::Selection : QClipboard::Clipboard);
96#else
97    return String();
98#endif
99}
100
101PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefPtr<Range> context,
102                                                          bool allowPlainText, bool& chosePlainText)
103{
104#ifndef QT_NO_CLIPBOARD
105    const QMimeData* mimeData = QApplication::clipboard()->mimeData(
106            m_selectionMode ? QClipboard::Selection : QClipboard::Clipboard);
107
108    chosePlainText = false;
109
110    if (mimeData->hasHtml()) {
111        QString html = mimeData->html();
112        if (!html.isEmpty()) {
113            RefPtr<DocumentFragment> fragment = createFragmentFromMarkup(frame->document(), html, "", FragmentScriptingNotAllowed);
114            if (fragment)
115                return fragment.release();
116        }
117    }
118
119    if (allowPlainText && mimeData->hasText()) {
120        chosePlainText = true;
121        RefPtr<DocumentFragment> fragment = createFragmentFromText(context.get(), mimeData->text());
122        if (fragment)
123            return fragment.release();
124    }
125#endif
126    return 0;
127}
128
129void Pasteboard::writePlainText(const String& text)
130{
131#ifndef QT_NO_CLIPBOARD
132    QMimeData* md = new QMimeData;
133    QString qtext = text;
134    qtext.replace(QChar(0xa0), QLatin1Char(' '));
135    md->setText(qtext);
136    QApplication::clipboard()->setMimeData(md, m_selectionMode ? QClipboard::Selection : QClipboard::Clipboard);
137#endif
138}
139
140void Pasteboard::writeURL(const KURL& url, const String&, Frame*)
141{
142    ASSERT(!url.isEmpty());
143
144#ifndef QT_NO_CLIPBOARD
145    QMimeData* md = new QMimeData;
146    QString urlString = url.string();
147    md->setText(urlString);
148    md->setUrls(QList<QUrl>() << url);
149    QApplication::clipboard()->setMimeData(md, m_selectionMode ? QClipboard::Selection : QClipboard::Clipboard);
150#endif
151}
152
153void Pasteboard::writeImage(Node* node, const KURL&, const String&)
154{
155    ASSERT(node && node->renderer() && node->renderer()->isImage());
156
157#ifndef QT_NO_CLIPBOARD
158    CachedImage* cachedImage = toRenderImage(node->renderer())->cachedImage();
159    if (!cachedImage || cachedImage->errorOccurred())
160        return;
161
162    Image* image = cachedImage->image();
163    ASSERT(image);
164
165    QPixmap* pixmap = image->nativeImageForCurrentFrame();
166    if (!pixmap)
167        return;
168    QApplication::clipboard()->setPixmap(*pixmap, QClipboard::Clipboard);
169#endif
170}
171
172/* This function is called from Editor::tryDHTMLCopy before actually set the clipboard
173 * It introduce a race condition with klipper, which will try to grab the clipboard
174 * It's not required to clear it anyway, since QClipboard take care about replacing the clipboard
175 */
176void Pasteboard::clear()
177{
178}
179
180bool Pasteboard::isSelectionMode() const
181{
182    return m_selectionMode;
183}
184
185void Pasteboard::setSelectionMode(bool selectionMode)
186{
187    m_selectionMode = selectionMode;
188}
189
190}
191