selection_utils.cc revision 868fa2fe829687343ffae624259930155e16dbd8
1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file. 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/base/x/selection_utils.h" 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <set> 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/i18n/icu_string_conversions.h" 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/logging.h" 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/base/clipboard/clipboard.h" 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/base/x/x11_atom_cache.h" 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace ui { 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kMimeTypeMozillaURL[] = "text/x-moz-url"; 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kString[] = "STRING"; 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kText[] = "TEXT"; 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kUtf8String[] = "UTF8_STRING"; 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char* kSelectionDataAtoms[] = { 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Clipboard::kMimeTypeHTML, 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kString, 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kText, 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kUtf8String, 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NULL 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::vector< ::Atom> GetTextAtomsFrom(const X11AtomCache* atom_cache) { 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::vector< ::Atom> atoms; 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) atoms.push_back(atom_cache->GetAtom(kString)); 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) atoms.push_back(atom_cache->GetAtom(kText)); 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) atoms.push_back(atom_cache->GetAtom(kUtf8String)); 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return atoms; 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::vector< ::Atom> GetURLAtomsFrom(const X11AtomCache* atom_cache) { 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::vector< ::Atom> atoms; 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) atoms.push_back(atom_cache->GetAtom(Clipboard::kMimeTypeURIList)); 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) atoms.push_back(atom_cache->GetAtom(kMimeTypeMozillaURL)); 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return atoms; 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void GetAtomIntersection(const std::vector< ::Atom>& one, 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::vector< ::Atom>& two, 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::vector< ::Atom>* output) { 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (std::vector< ::Atom>::const_iterator it = one.begin(); it != one.end(); 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ++it) { 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (std::vector< ::Atom>::const_iterator jt = two.begin(); jt != two.end(); 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ++jt) { 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (*it == *jt) { 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) output->push_back(*it); 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)SelectionFormatMap::SelectionFormatMap() {} 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)SelectionFormatMap::~SelectionFormatMap() { 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // WriteText() inserts the same pointer multiple times for different 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // representations; we need to dedupe it. 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::set<char*> to_delete; 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (InternalMap::iterator it = data_.begin(); it != data_.end(); ++it) 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) to_delete.insert(it->second.first); 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (std::set<char*>::iterator it = to_delete.begin(); it != to_delete.end(); 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ++it) { 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) delete [] *it; 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SelectionFormatMap::Insert(::Atom atom, char* data, size_t size) { 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(data_.find(atom) == data_.end()); 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) data_.insert(std::make_pair(atom, std::make_pair(data, size))); 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)SelectionData::SelectionData(Display* x_display) 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : type_(None), 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) data_(NULL), 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) size_(0), 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) owned_(false), 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) atom_cache_(x_display, kSelectionDataAtoms) { 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)SelectionData::~SelectionData() { 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (owned_) 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) XFree(data_); 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SelectionData::Set(::Atom type, char* data, size_t size, bool owned) { 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (owned_) 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) XFree(data_); 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) type_ = type; 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) data_ = data; 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) size_ = size; 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) owned_ = owned; 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string SelectionData::GetText() const { 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (type_ == atom_cache_.GetAtom(kUtf8String) || 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) type_ == atom_cache_.GetAtom(kText)) { 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(data_, size_); 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else if (type_ == atom_cache_.GetAtom(kString)) { 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string result; 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::ConvertToUtf8AndNormalize(std::string(data_, size_), 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::kCodepageLatin1, 115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) &result); 116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return result; 117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // BTW, I looked at COMPOUND_TEXT, and there's no way we're going to 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // support that. Yuck. 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NOTREACHED(); 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(); 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)string16 SelectionData::GetHtml() const { 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) string16 markup; 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (type_ == atom_cache_.GetAtom(Clipboard::kMimeTypeHTML)) { 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // If the data starts with 0xFEFF, i.e., Byte Order Mark, assume it is 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // UTF-16, otherwise assume UTF-8. 131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (size_ >= 2 && 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) reinterpret_cast<const uint16_t*>(data_)[0] == 0xFEFF) { 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) markup.assign(reinterpret_cast<const uint16_t*>(data_) + 1, 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) (size_ / 2) - 1); 135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UTF8ToUTF16(reinterpret_cast<const char*>(data_), size_, &markup); 137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // If there is a terminating NULL, drop it. 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!markup.empty() && markup.at(markup.length() - 1) == '\0') 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) markup.resize(markup.length() - 1); 142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return markup; 144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NOTREACHED(); 146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return markup; 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SelectionData::AssignTo(std::string* result) const { 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) result->assign(data_, size_); 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SelectionData::AssignTo(string16* result) const { 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) result->assign(reinterpret_cast<base::char16*>(data_), size_ / 2); 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace ui 159