| Index: ui/base/x/selection_utils.cc
|
| diff --git a/ui/base/x/selection_utils.cc b/ui/base/x/selection_utils.cc
|
| index 5dd6f681ce129ab01388a4068fcd5154410dffc5..560f494a0c6c1b94c598cb52f1df03d8a74abf68 100644
|
| --- a/ui/base/x/selection_utils.cc
|
| +++ b/ui/base/x/selection_utils.cc
|
| @@ -58,56 +58,66 @@ void GetAtomIntersection(const std::vector< ::Atom>& one,
|
| }
|
| }
|
|
|
| -///////////////////////////////////////////////////////////////////////////////
|
| +void AddString16ToVector(const string16& str,
|
| + std::vector<unsigned char>* bytes) {
|
| + const unsigned char* front =
|
| + reinterpret_cast<const unsigned char*>(str.data());
|
| + bytes->insert(bytes->end(), front, front + (str.size() * 2));
|
| +}
|
|
|
| -SelectionFormatMap::SelectionFormatMap() {}
|
| +std::string RefCountedMemoryToString(
|
| + const scoped_refptr<base::RefCountedMemory>& memory) {
|
| + if (!memory) {
|
| + NOTREACHED();
|
| + return std::string();
|
| + }
|
|
|
| -SelectionFormatMap::~SelectionFormatMap() {
|
| - // WriteText() inserts the same pointer multiple times for different
|
| - // representations; we need to dedupe it.
|
| - std::set<char*> to_delete;
|
| - for (InternalMap::iterator it = data_.begin(); it != data_.end(); ++it)
|
| - to_delete.insert(it->second.first);
|
| + size_t size = memory->size();
|
| + if (!size)
|
| + return std::string();
|
|
|
| - for (std::set<char*>::iterator it = to_delete.begin(); it != to_delete.end();
|
| - ++it) {
|
| - delete [] *it;
|
| + const unsigned char* front = memory->front();
|
| + return std::string(reinterpret_cast<const char*>(front), size);
|
| +}
|
| +
|
| +string16 RefCountedMemoryToString16(
|
| + const scoped_refptr<base::RefCountedMemory>& memory) {
|
| + if (!memory) {
|
| + NOTREACHED();
|
| + return string16();
|
| }
|
| +
|
| + size_t size = memory->size();
|
| + if (!size)
|
| + return string16();
|
| +
|
| + const unsigned char* front = memory->front();
|
| + return string16(reinterpret_cast<const base::char16*>(front), size / 2);
|
| }
|
|
|
| -void SelectionFormatMap::Insert(::Atom atom, char* data, size_t size) {
|
| - // Views code often inserts the same content multiple times, so we have to
|
| - // free old data. Only call delete when it's the last pointer we have to that
|
| - // data.
|
| - InternalMap::iterator exists_it = data_.find(atom);
|
| - if (exists_it != data_.end()) {
|
| - int count = 0;
|
| - for (InternalMap::iterator it = data_.begin(); it != data_.end(); ++it) {
|
| - if (it->second.first == exists_it->second.first)
|
| - count++;
|
| - }
|
| +///////////////////////////////////////////////////////////////////////////////
|
|
|
| - if (count == 1)
|
| - delete [] exists_it->second.first;
|
| - }
|
| +SelectionFormatMap::SelectionFormatMap() {}
|
| +
|
| +SelectionFormatMap::~SelectionFormatMap() {}
|
|
|
| - data_.insert(std::make_pair(atom, std::make_pair(data, size)));
|
| +void SelectionFormatMap::Insert(
|
| + ::Atom atom,
|
| + const scoped_refptr<base::RefCountedMemory>& item) {
|
| + data_.insert(std::make_pair(atom, item));
|
| }
|
|
|
| -ui::SelectionData* SelectionFormatMap::GetFirstOf(
|
| +ui::SelectionData SelectionFormatMap::GetFirstOf(
|
| const std::vector< ::Atom>& requested_types) const {
|
| for (std::vector< ::Atom>::const_iterator it = requested_types.begin();
|
| it != requested_types.end(); ++it) {
|
| const_iterator data_it = data_.find(*it);
|
| if (data_it != data_.end()) {
|
| - ui::SelectionData* data = new SelectionData;
|
| - data->Set(data_it->first, data_it->second.first, data_it->second.second,
|
| - false);
|
| - return data;
|
| + return SelectionData(data_it->first, data_it->second);
|
| }
|
| }
|
|
|
| - return NULL;
|
| + return SelectionData();
|
| }
|
|
|
| std::vector< ::Atom> SelectionFormatMap::GetTypes() const {
|
| @@ -118,50 +128,60 @@ std::vector< ::Atom> SelectionFormatMap::GetTypes() const {
|
| return atoms;
|
| }
|
|
|
| -scoped_ptr<SelectionFormatMap> SelectionFormatMap::Clone() const {
|
| - scoped_ptr<SelectionFormatMap> ret(new SelectionFormatMap);
|
| -
|
| - for (const_iterator it = data_.begin(); it != data_.end(); ++it) {
|
| - char* data_copy = new char[it->second.second];
|
| - memcpy(data_copy, it->second.first, it->second.second);
|
| - ret->Insert(it->first, data_copy, it->second.second);
|
| - }
|
| -
|
| - return ret.Pass();
|
| -}
|
| -
|
| ///////////////////////////////////////////////////////////////////////////////
|
|
|
| SelectionData::SelectionData()
|
| : type_(None),
|
| - data_(NULL),
|
| - size_(0),
|
| - owned_(false),
|
| atom_cache_(ui::GetXDisplay(), kSelectionDataAtoms) {
|
| }
|
|
|
| -SelectionData::~SelectionData() {
|
| - if (owned_)
|
| - XFree(data_);
|
| +SelectionData::SelectionData(
|
| + ::Atom type,
|
| + const scoped_refptr<base::RefCountedMemory>& memory)
|
| + : type_(type),
|
| + memory_(memory),
|
| + atom_cache_(ui::GetXDisplay(), kSelectionDataAtoms) {
|
| +}
|
| +
|
| +SelectionData::SelectionData(const SelectionData& rhs)
|
| + : type_(rhs.type_),
|
| + memory_(rhs.memory_),
|
| + atom_cache_(ui::GetXDisplay(), kSelectionDataAtoms) {
|
| +}
|
| +
|
| +SelectionData::~SelectionData() {}
|
| +
|
| +SelectionData& SelectionData::operator=(const SelectionData& rhs) {
|
| + type_ = rhs.type_;
|
| + memory_ = rhs.memory_;
|
| + // TODO(erg): In some future where we have to support multiple X Displays,
|
| + // the following will also need to deal with the display.
|
| + return *this;
|
| }
|
|
|
| -void SelectionData::Set(::Atom type, char* data, size_t size, bool owned) {
|
| - if (owned_)
|
| - XFree(data_);
|
| +bool SelectionData::IsValid() const {
|
| + return type_ != None;
|
| +}
|
|
|
| - type_ = type;
|
| - data_ = data;
|
| - size_ = size;
|
| - owned_ = owned;
|
| +::Atom SelectionData::GetType() const {
|
| + return type_;
|
| +}
|
| +
|
| +const unsigned char* SelectionData::GetData() const {
|
| + return memory_ ? memory_->front() : NULL;
|
| +}
|
| +
|
| +size_t SelectionData::GetSize() const {
|
| + return memory_ ? memory_->size() : 0;
|
| }
|
|
|
| std::string SelectionData::GetText() const {
|
| if (type_ == atom_cache_.GetAtom(kUtf8String) ||
|
| type_ == atom_cache_.GetAtom(kText)) {
|
| - return std::string(data_, size_);
|
| + return RefCountedMemoryToString(memory_);
|
| } else if (type_ == atom_cache_.GetAtom(kString)) {
|
| std::string result;
|
| - base::ConvertToUtf8AndNormalize(std::string(data_, size_),
|
| + base::ConvertToUtf8AndNormalize(RefCountedMemoryToString(memory_),
|
| base::kCodepageLatin1,
|
| &result);
|
| return result;
|
| @@ -177,14 +197,17 @@ string16 SelectionData::GetHtml() const {
|
| string16 markup;
|
|
|
| if (type_ == atom_cache_.GetAtom(Clipboard::kMimeTypeHTML)) {
|
| + const unsigned char* data = GetData();
|
| + size_t size = GetSize();
|
| +
|
| // If the data starts with 0xFEFF, i.e., Byte Order Mark, assume it is
|
| // UTF-16, otherwise assume UTF-8.
|
| - if (size_ >= 2 &&
|
| - reinterpret_cast<const uint16_t*>(data_)[0] == 0xFEFF) {
|
| - markup.assign(reinterpret_cast<const uint16_t*>(data_) + 1,
|
| - (size_ / 2) - 1);
|
| + if (size >= 2 &&
|
| + reinterpret_cast<const uint16_t*>(data)[0] == 0xFEFF) {
|
| + markup.assign(reinterpret_cast<const uint16_t*>(data) + 1,
|
| + (size / 2) - 1);
|
| } else {
|
| - UTF8ToUTF16(reinterpret_cast<const char*>(data_), size_, &markup);
|
| + UTF8ToUTF16(reinterpret_cast<const char*>(data), size, &markup);
|
| }
|
|
|
| // If there is a terminating NULL, drop it.
|
| @@ -199,11 +222,11 @@ string16 SelectionData::GetHtml() const {
|
| }
|
|
|
| void SelectionData::AssignTo(std::string* result) const {
|
| - result->assign(data_, size_);
|
| + *result = RefCountedMemoryToString(memory_);
|
| }
|
|
|
| void SelectionData::AssignTo(string16* result) const {
|
| - result->assign(reinterpret_cast<base::char16*>(data_), size_ / 2);
|
| + *result = RefCountedMemoryToString16(memory_);
|
| }
|
|
|
| } // namespace ui
|
|
|