1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/base/x/selection_utils.h"
9 #include "base/i18n/icu_string_conversions.h"
10 #include "base/logging.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "ui/base/clipboard/clipboard.h"
14 #include "ui/base/x/x11_util.h"
15 #include "ui/gfx/x/x11_atom_cache.h"
19 const char kMimeTypeMozillaURL
[] = "text/x-moz-url";
20 const char kString
[] = "STRING";
21 const char kText
[] = "TEXT";
22 const char kTextPlain
[] = "text/plain";
23 const char kTextPlainUtf8
[] = "text/plain;charset=utf-8";
24 const char kUtf8String
[] = "UTF8_STRING";
26 const char* kSelectionDataAtoms
[] = {
27 Clipboard::kMimeTypeHTML
,
36 std::vector
< ::Atom
> GetTextAtomsFrom(const X11AtomCache
* atom_cache
) {
37 std::vector
< ::Atom
> atoms
;
38 atoms
.push_back(atom_cache
->GetAtom(kUtf8String
));
39 atoms
.push_back(atom_cache
->GetAtom(kString
));
40 atoms
.push_back(atom_cache
->GetAtom(kText
));
41 atoms
.push_back(atom_cache
->GetAtom(kTextPlain
));
42 atoms
.push_back(atom_cache
->GetAtom(kTextPlainUtf8
));
46 std::vector
< ::Atom
> GetURLAtomsFrom(const X11AtomCache
* atom_cache
) {
47 std::vector
< ::Atom
> atoms
;
48 atoms
.push_back(atom_cache
->GetAtom(Clipboard::kMimeTypeURIList
));
49 atoms
.push_back(atom_cache
->GetAtom(kMimeTypeMozillaURL
));
53 std::vector
< ::Atom
> GetURIListAtomsFrom(const X11AtomCache
* atom_cache
) {
54 std::vector
< ::Atom
> atoms
;
55 atoms
.push_back(atom_cache
->GetAtom(Clipboard::kMimeTypeURIList
));
59 void GetAtomIntersection(const std::vector
< ::Atom
>& desired
,
60 const std::vector
< ::Atom
>& offered
,
61 std::vector
< ::Atom
>* output
) {
62 for (std::vector
< ::Atom
>::const_iterator it
= desired
.begin();
63 it
!= desired
.end(); ++it
) {
64 std::vector
< ::Atom
>::const_iterator jt
=
65 std::find(offered
.begin(), offered
.end(), *it
);
66 if (jt
!= offered
.end())
67 output
->push_back(*it
);
71 void AddString16ToVector(const base::string16
& str
,
72 std::vector
<unsigned char>* bytes
) {
73 const unsigned char* front
=
74 reinterpret_cast<const unsigned char*>(str
.data());
75 bytes
->insert(bytes
->end(), front
, front
+ (str
.size() * 2));
78 std::vector
<std::string
> ParseURIList(const SelectionData
& data
) {
79 // uri-lists are newline separated file lists in URL encoding.
81 data
.AssignTo(&unparsed
);
83 std::vector
<std::string
> tokens
;
84 Tokenize(unparsed
, "\n", &tokens
);
88 std::string
RefCountedMemoryToString(
89 const scoped_refptr
<base::RefCountedMemory
>& memory
) {
95 size_t size
= memory
->size();
99 const unsigned char* front
= memory
->front();
100 return std::string(reinterpret_cast<const char*>(front
), size
);
103 base::string16
RefCountedMemoryToString16(
104 const scoped_refptr
<base::RefCountedMemory
>& memory
) {
107 return base::string16();
110 size_t size
= memory
->size();
112 return base::string16();
114 const unsigned char* front
= memory
->front();
115 return base::string16(reinterpret_cast<const base::char16
*>(front
), size
/ 2);
118 ///////////////////////////////////////////////////////////////////////////////
120 SelectionFormatMap::SelectionFormatMap() {}
122 SelectionFormatMap::~SelectionFormatMap() {}
124 void SelectionFormatMap::Insert(
126 const scoped_refptr
<base::RefCountedMemory
>& item
) {
128 data_
.insert(std::make_pair(atom
, item
));
131 ui::SelectionData
SelectionFormatMap::GetFirstOf(
132 const std::vector
< ::Atom
>& requested_types
) const {
133 for (std::vector
< ::Atom
>::const_iterator it
= requested_types
.begin();
134 it
!= requested_types
.end(); ++it
) {
135 const_iterator data_it
= data_
.find(*it
);
136 if (data_it
!= data_
.end()) {
137 return SelectionData(data_it
->first
, data_it
->second
);
141 return SelectionData();
144 std::vector
< ::Atom
> SelectionFormatMap::GetTypes() const {
145 std::vector
< ::Atom
> atoms
;
146 for (const_iterator it
= data_
.begin(); it
!= data_
.end(); ++it
)
147 atoms
.push_back(it
->first
);
152 ///////////////////////////////////////////////////////////////////////////////
154 SelectionData::SelectionData()
156 atom_cache_(gfx::GetXDisplay(), kSelectionDataAtoms
) {
159 SelectionData::SelectionData(
161 const scoped_refptr
<base::RefCountedMemory
>& memory
)
164 atom_cache_(gfx::GetXDisplay(), kSelectionDataAtoms
) {
167 SelectionData::SelectionData(const SelectionData
& rhs
)
169 memory_(rhs
.memory_
),
170 atom_cache_(gfx::GetXDisplay(), kSelectionDataAtoms
) {
173 SelectionData::~SelectionData() {}
175 SelectionData
& SelectionData::operator=(const SelectionData
& rhs
) {
177 memory_
= rhs
.memory_
;
178 // TODO(erg): In some future where we have to support multiple X Displays,
179 // the following will also need to deal with the display.
183 bool SelectionData::IsValid() const {
184 return type_
!= None
;
187 ::Atom
SelectionData::GetType() const {
191 const unsigned char* SelectionData::GetData() const {
192 return memory_
.get() ? memory_
->front() : NULL
;
195 size_t SelectionData::GetSize() const {
196 return memory_
.get() ? memory_
->size() : 0;
199 std::string
SelectionData::GetText() const {
200 if (type_
== atom_cache_
.GetAtom(kUtf8String
) ||
201 type_
== atom_cache_
.GetAtom(kText
) ||
202 type_
== atom_cache_
.GetAtom(kTextPlainUtf8
)) {
203 return RefCountedMemoryToString(memory_
);
204 } else if (type_
== atom_cache_
.GetAtom(kString
) ||
205 type_
== atom_cache_
.GetAtom(kTextPlain
)) {
207 base::ConvertToUtf8AndNormalize(RefCountedMemoryToString(memory_
),
208 base::kCodepageLatin1
,
212 // BTW, I looked at COMPOUND_TEXT, and there's no way we're going to
213 // support that. Yuck.
215 return std::string();
219 base::string16
SelectionData::GetHtml() const {
220 base::string16 markup
;
222 if (type_
== atom_cache_
.GetAtom(Clipboard::kMimeTypeHTML
)) {
223 const unsigned char* data
= GetData();
224 size_t size
= GetSize();
226 // If the data starts with 0xFEFF, i.e., Byte Order Mark, assume it is
227 // UTF-16, otherwise assume UTF-8.
229 reinterpret_cast<const uint16_t*>(data
)[0] == 0xFEFF) {
230 markup
.assign(reinterpret_cast<const uint16_t*>(data
) + 1,
233 base::UTF8ToUTF16(reinterpret_cast<const char*>(data
), size
, &markup
);
236 // If there is a terminating NULL, drop it.
237 if (!markup
.empty() && markup
.at(markup
.length() - 1) == '\0')
238 markup
.resize(markup
.length() - 1);
247 void SelectionData::AssignTo(std::string
* result
) const {
248 *result
= RefCountedMemoryToString(memory_
);
251 void SelectionData::AssignTo(base::string16
* result
) const {
252 *result
= RefCountedMemoryToString16(memory_
);