1/*
2 * Copyright (C) 2009, Martin Robinson
3 *
4 *  This library is free software; you can redistribute it and/or
5 *  modify it under the terms of the GNU Lesser General Public
6 *  License as published by the Free Software Foundation; either
7 *  version 2 of the License, or (at your option) any later version.
8 *
9 *  This library is distributed in the hope that it will be useful,
10 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 *  Lesser General Public License for more details.
13 *
14 *  You should have received a copy of the GNU Lesser General Public
15 *  License along with this library; if not, write to the Free Software
16 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17 */
18
19#include "config.h"
20#include "DataObjectGtk.h"
21
22#include "markup.h"
23#include <gtk/gtk.h>
24#include <wtf/gobject/GUniquePtr.h>
25#include <wtf/text/StringBuilder.h>
26
27namespace WebCore {
28
29static void replaceNonBreakingSpaceWithSpace(String& str)
30{
31    static const UChar NonBreakingSpaceCharacter = 0xA0;
32    static const UChar SpaceCharacter = ' ';
33    str.replace(NonBreakingSpaceCharacter, SpaceCharacter);
34}
35
36String DataObjectGtk::text() const
37{
38    if (m_range) {
39        String text = m_range->text();
40        replaceNonBreakingSpaceWithSpace(text);
41        return text;
42    }
43    return m_text;
44}
45
46String DataObjectGtk::markup() const
47{
48    if (m_range)
49        return createMarkup(*m_range, 0, AnnotateForInterchange, false, ResolveNonLocalURLs);
50    return m_markup;
51}
52
53HashMap<String, String> DataObjectGtk::unknownTypes() const
54{
55    return m_unknownTypeData;
56}
57
58void DataObjectGtk::setText(const String& newText)
59{
60    m_range = 0;
61    m_text = newText;
62    replaceNonBreakingSpaceWithSpace(m_text);
63}
64
65void DataObjectGtk::setMarkup(const String& newMarkup)
66{
67    m_range = 0;
68    m_markup = newMarkup;
69}
70
71void DataObjectGtk::setURIList(const String& uriListString)
72{
73    m_uriList = uriListString;
74
75    // This code is originally from: platform/chromium/ChromiumDataObject.cpp.
76    // FIXME: We should make this code cross-platform eventually.
77
78    // Line separator is \r\n per RFC 2483 - however, for compatibility
79    // reasons we also allow just \n here.
80    Vector<String> uriList;
81    uriListString.split('\n', uriList);
82
83    // Process the input and copy the first valid URL into the url member.
84    // In case no URLs can be found, subsequent calls to getData("URL")
85    // will get an empty string. This is in line with the HTML5 spec (see
86    // "The DragEvent and DataTransfer interfaces"). Also extract all filenames
87    // from the URI list.
88    bool setURL = false;
89    for (size_t i = 0; i < uriList.size(); ++i) {
90        String& line = uriList[i];
91        line = line.stripWhiteSpace();
92        if (line.isEmpty())
93            continue;
94        if (line[0] == '#')
95            continue;
96
97        URL url = URL(URL(), line);
98        if (url.isValid()) {
99            if (!setURL) {
100                m_url = url;
101                setURL = true;
102            }
103
104            GUniqueOutPtr<GError> error;
105            GUniquePtr<gchar> filename(g_filename_from_uri(line.utf8().data(), 0, &error.outPtr()));
106            if (!error && filename)
107                m_filenames.append(String::fromUTF8(filename.get()));
108        }
109    }
110}
111
112void DataObjectGtk::setURL(const URL& url, const String& label)
113{
114    m_url = url;
115    m_uriList = url;
116    setText(url.string());
117
118    String actualLabel(label);
119    if (actualLabel.isEmpty())
120        actualLabel = url;
121
122    StringBuilder markup;
123    markup.append("<a href=\"");
124    markup.append(url.string());
125    markup.append("\">");
126    GUniquePtr<gchar> escaped(g_markup_escape_text(actualLabel.utf8().data(), -1));
127    markup.append(String::fromUTF8(escaped.get()));
128    markup.append("</a>");
129    setMarkup(markup.toString());
130}
131
132void DataObjectGtk::clearText()
133{
134    m_range = 0;
135    m_text = "";
136}
137
138void DataObjectGtk::clearMarkup()
139{
140    m_range = 0;
141    m_markup = "";
142}
143
144String DataObjectGtk::urlLabel() const
145{
146    if (hasText())
147        return text();
148
149    if (hasURL())
150        return url();
151
152    return String();
153}
154
155void DataObjectGtk::clearAllExceptFilenames()
156{
157    m_text = "";
158    m_markup = "";
159    m_uriList = "";
160    m_url = URL();
161    m_image = 0;
162    m_range = 0;
163    m_unknownTypeData.clear();
164}
165
166void DataObjectGtk::clearAll()
167{
168    clearAllExceptFilenames();
169    m_filenames.clear();
170}
171
172DataObjectGtk* DataObjectGtk::forClipboard(GtkClipboard* clipboard)
173{
174    static HashMap<GtkClipboard*, RefPtr<DataObjectGtk> > objectMap;
175
176    if (!objectMap.contains(clipboard)) {
177        RefPtr<DataObjectGtk> dataObject = DataObjectGtk::create();
178        objectMap.set(clipboard, dataObject);
179        return dataObject.get();
180    }
181
182    HashMap<GtkClipboard*, RefPtr<DataObjectGtk> >::iterator it = objectMap.find(clipboard);
183    return it->value.get();
184}
185
186}
187