| OLD | NEW | 
|    1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |    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 |    2 // Use of this source code is governed by a BSD-style license that can be | 
|    3 // found in the LICENSE file. |    3 // found in the LICENSE file. | 
|    4  |    4  | 
|    5 #include "ui/base/x/selection_utils.h" |    5 #include "ui/base/x/selection_utils.h" | 
|    6  |    6  | 
|    7 #include <set> |    7 #include <set> | 
|    8  |    8  | 
|    9 #include "base/i18n/icu_string_conversions.h" |    9 #include "base/i18n/icu_string_conversions.h" | 
|   10 #include "base/logging.h" |   10 #include "base/logging.h" | 
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   51     for (std::vector< ::Atom>::const_iterator jt = two.begin(); jt != two.end(); |   51     for (std::vector< ::Atom>::const_iterator jt = two.begin(); jt != two.end(); | 
|   52          ++jt) { |   52          ++jt) { | 
|   53       if (*it == *jt) { |   53       if (*it == *jt) { | 
|   54         output->push_back(*it); |   54         output->push_back(*it); | 
|   55         break; |   55         break; | 
|   56       } |   56       } | 
|   57     } |   57     } | 
|   58   } |   58   } | 
|   59 } |   59 } | 
|   60  |   60  | 
 |   61 void AddString16ToVector(const string16& str, | 
 |   62                          std::vector<unsigned char>* bytes) { | 
 |   63   const unsigned char* front = | 
 |   64       reinterpret_cast<const unsigned char*>(str.data()); | 
 |   65   bytes->insert(bytes->end(), front, front + (str.size() * 2)); | 
 |   66 } | 
 |   67  | 
 |   68 std::string RefCountedMemoryToString( | 
 |   69     const scoped_refptr<base::RefCountedMemory>& memory) { | 
 |   70   if (!memory) { | 
 |   71     NOTREACHED(); | 
 |   72     return std::string(); | 
 |   73   } | 
 |   74  | 
 |   75   size_t size = memory->size(); | 
 |   76   if (!size) | 
 |   77     return std::string(); | 
 |   78  | 
 |   79   const unsigned char* front = memory->front(); | 
 |   80   return std::string(reinterpret_cast<const char*>(front), size); | 
 |   81 } | 
 |   82  | 
 |   83 string16 RefCountedMemoryToString16( | 
 |   84     const scoped_refptr<base::RefCountedMemory>& memory) { | 
 |   85   if (!memory) { | 
 |   86     NOTREACHED(); | 
 |   87     return string16(); | 
 |   88   } | 
 |   89  | 
 |   90   size_t size = memory->size(); | 
 |   91   if (!size) | 
 |   92     return string16(); | 
 |   93  | 
 |   94   const unsigned char* front = memory->front(); | 
 |   95   return string16(reinterpret_cast<const base::char16*>(front), size / 2); | 
 |   96 } | 
 |   97  | 
|   61 /////////////////////////////////////////////////////////////////////////////// |   98 /////////////////////////////////////////////////////////////////////////////// | 
|   62  |   99  | 
|   63 SelectionFormatMap::SelectionFormatMap() {} |  100 SelectionFormatMap::SelectionFormatMap() {} | 
|   64  |  101  | 
|   65 SelectionFormatMap::~SelectionFormatMap() { |  102 SelectionFormatMap::~SelectionFormatMap() {} | 
|   66   // WriteText() inserts the same pointer multiple times for different |  | 
|   67   // representations; we need to dedupe it. |  | 
|   68   std::set<char*> to_delete; |  | 
|   69   for (InternalMap::iterator it = data_.begin(); it != data_.end(); ++it) |  | 
|   70     to_delete.insert(it->second.first); |  | 
|   71  |  103  | 
|   72   for (std::set<char*>::iterator it = to_delete.begin(); it != to_delete.end(); |  104 void SelectionFormatMap::Insert( | 
|   73        ++it) { |  105     ::Atom atom, | 
|   74     delete [] *it; |  106     const scoped_refptr<base::RefCountedMemory>& item) { | 
|   75   } |  107   data_.insert(std::make_pair(atom, item)); | 
|   76 } |  108 } | 
|   77  |  109  | 
|   78 void SelectionFormatMap::Insert(::Atom atom, char* data, size_t size) { |  110 ui::SelectionData SelectionFormatMap::GetFirstOf( | 
|   79   // Views code often inserts the same content multiple times, so we have to |  | 
|   80   // free old data. Only call delete when it's the last pointer we have to that |  | 
|   81   // data. |  | 
|   82   InternalMap::iterator exists_it = data_.find(atom); |  | 
|   83   if (exists_it != data_.end()) { |  | 
|   84     int count = 0; |  | 
|   85     for (InternalMap::iterator it = data_.begin(); it != data_.end(); ++it) { |  | 
|   86       if (it->second.first == exists_it->second.first) |  | 
|   87         count++; |  | 
|   88     } |  | 
|   89  |  | 
|   90     if (count == 1) |  | 
|   91       delete [] exists_it->second.first; |  | 
|   92   } |  | 
|   93  |  | 
|   94   data_.insert(std::make_pair(atom, std::make_pair(data, size))); |  | 
|   95 } |  | 
|   96  |  | 
|   97 ui::SelectionData* SelectionFormatMap::GetFirstOf( |  | 
|   98     const std::vector< ::Atom>& requested_types) const { |  111     const std::vector< ::Atom>& requested_types) const { | 
|   99   for (std::vector< ::Atom>::const_iterator it = requested_types.begin(); |  112   for (std::vector< ::Atom>::const_iterator it = requested_types.begin(); | 
|  100        it != requested_types.end(); ++it) { |  113        it != requested_types.end(); ++it) { | 
|  101     const_iterator data_it = data_.find(*it); |  114     const_iterator data_it = data_.find(*it); | 
|  102     if (data_it != data_.end()) { |  115     if (data_it != data_.end()) { | 
|  103       ui::SelectionData* data = new SelectionData; |  116       return SelectionData(data_it->first, data_it->second); | 
|  104       data->Set(data_it->first, data_it->second.first, data_it->second.second, |  | 
|  105                 false); |  | 
|  106       return data; |  | 
|  107     } |  117     } | 
|  108   } |  118   } | 
|  109  |  119  | 
|  110   return NULL; |  120   return SelectionData(); | 
|  111 } |  121 } | 
|  112  |  122  | 
|  113 std::vector< ::Atom> SelectionFormatMap::GetTypes() const { |  123 std::vector< ::Atom> SelectionFormatMap::GetTypes() const { | 
|  114   std::vector< ::Atom> atoms; |  124   std::vector< ::Atom> atoms; | 
|  115   for (const_iterator it = data_.begin(); it != data_.end(); ++it) |  125   for (const_iterator it = data_.begin(); it != data_.end(); ++it) | 
|  116     atoms.push_back(it->first); |  126     atoms.push_back(it->first); | 
|  117  |  127  | 
|  118   return atoms; |  128   return atoms; | 
|  119 } |  129 } | 
|  120  |  130  | 
|  121 scoped_ptr<SelectionFormatMap> SelectionFormatMap::Clone() const { |  | 
|  122   scoped_ptr<SelectionFormatMap> ret(new SelectionFormatMap); |  | 
|  123  |  | 
|  124   for (const_iterator it = data_.begin(); it != data_.end(); ++it) { |  | 
|  125     char* data_copy = new char[it->second.second]; |  | 
|  126     memcpy(data_copy, it->second.first, it->second.second); |  | 
|  127     ret->Insert(it->first, data_copy, it->second.second); |  | 
|  128   } |  | 
|  129  |  | 
|  130   return ret.Pass(); |  | 
|  131 } |  | 
|  132  |  | 
|  133 /////////////////////////////////////////////////////////////////////////////// |  131 /////////////////////////////////////////////////////////////////////////////// | 
|  134  |  132  | 
|  135 SelectionData::SelectionData() |  133 SelectionData::SelectionData() | 
|  136     : type_(None), |  134     : type_(None), | 
|  137       data_(NULL), |  | 
|  138       size_(0), |  | 
|  139       owned_(false), |  | 
|  140       atom_cache_(ui::GetXDisplay(), kSelectionDataAtoms) { |  135       atom_cache_(ui::GetXDisplay(), kSelectionDataAtoms) { | 
|  141 } |  136 } | 
|  142  |  137  | 
|  143 SelectionData::~SelectionData() { |  138 SelectionData::SelectionData( | 
|  144   if (owned_) |  139     ::Atom type, | 
|  145     XFree(data_); |  140     const scoped_refptr<base::RefCountedMemory>& memory) | 
 |  141     : type_(type), | 
 |  142       memory_(memory), | 
 |  143       atom_cache_(ui::GetXDisplay(), kSelectionDataAtoms) { | 
|  146 } |  144 } | 
|  147  |  145  | 
|  148 void SelectionData::Set(::Atom type, char* data, size_t size, bool owned) { |  146 SelectionData::SelectionData(const SelectionData& rhs) | 
|  149   if (owned_) |  147     : type_(rhs.type_), | 
|  150     XFree(data_); |  148       memory_(rhs.memory_), | 
 |  149       atom_cache_(ui::GetXDisplay(), kSelectionDataAtoms) { | 
 |  150 } | 
|  151  |  151  | 
|  152   type_ = type; |  152 SelectionData::~SelectionData() {} | 
|  153   data_ = data; |  153  | 
|  154   size_ = size; |  154 SelectionData& SelectionData::operator=(const SelectionData& rhs) { | 
|  155   owned_ = owned; |  155   type_ = rhs.type_; | 
 |  156   memory_ = rhs.memory_; | 
 |  157   // TODO(erg): In some future where we have to support multiple X Displays, | 
 |  158   // the following will also need to deal with the display. | 
 |  159   return *this; | 
 |  160 } | 
 |  161  | 
 |  162 bool SelectionData::IsValid() const { | 
 |  163   return type_ != None; | 
 |  164 } | 
 |  165  | 
 |  166 ::Atom SelectionData::GetType() const { | 
 |  167   return type_; | 
 |  168 } | 
 |  169  | 
 |  170 const unsigned char* SelectionData::GetData() const { | 
 |  171   return memory_ ? memory_->front() : NULL; | 
 |  172 } | 
 |  173  | 
 |  174 size_t SelectionData::GetSize() const { | 
 |  175   return memory_ ? memory_->size() : 0; | 
|  156 } |  176 } | 
|  157  |  177  | 
|  158 std::string SelectionData::GetText() const { |  178 std::string SelectionData::GetText() const { | 
|  159   if (type_ == atom_cache_.GetAtom(kUtf8String) || |  179   if (type_ == atom_cache_.GetAtom(kUtf8String) || | 
|  160       type_ == atom_cache_.GetAtom(kText)) { |  180       type_ == atom_cache_.GetAtom(kText)) { | 
|  161     return std::string(data_, size_); |  181     return RefCountedMemoryToString(memory_); | 
|  162   } else if (type_ == atom_cache_.GetAtom(kString)) { |  182   } else if (type_ == atom_cache_.GetAtom(kString)) { | 
|  163     std::string result; |  183     std::string result; | 
|  164     base::ConvertToUtf8AndNormalize(std::string(data_, size_), |  184     base::ConvertToUtf8AndNormalize(RefCountedMemoryToString(memory_), | 
|  165                                     base::kCodepageLatin1, |  185                                     base::kCodepageLatin1, | 
|  166                                     &result); |  186                                     &result); | 
|  167     return result; |  187     return result; | 
|  168   } else { |  188   } else { | 
|  169     // BTW, I looked at COMPOUND_TEXT, and there's no way we're going to |  189     // BTW, I looked at COMPOUND_TEXT, and there's no way we're going to | 
|  170     // support that. Yuck. |  190     // support that. Yuck. | 
|  171     NOTREACHED(); |  191     NOTREACHED(); | 
|  172     return std::string(); |  192     return std::string(); | 
|  173   } |  193   } | 
|  174 } |  194 } | 
|  175  |  195  | 
|  176 string16 SelectionData::GetHtml() const { |  196 string16 SelectionData::GetHtml() const { | 
|  177   string16 markup; |  197   string16 markup; | 
|  178  |  198  | 
|  179   if (type_ == atom_cache_.GetAtom(Clipboard::kMimeTypeHTML)) { |  199   if (type_ == atom_cache_.GetAtom(Clipboard::kMimeTypeHTML)) { | 
 |  200     const unsigned char* data = GetData(); | 
 |  201     size_t size = GetSize(); | 
 |  202  | 
|  180     // If the data starts with 0xFEFF, i.e., Byte Order Mark, assume it is |  203     // If the data starts with 0xFEFF, i.e., Byte Order Mark, assume it is | 
|  181     // UTF-16, otherwise assume UTF-8. |  204     // UTF-16, otherwise assume UTF-8. | 
|  182     if (size_ >= 2 && |  205     if (size >= 2 && | 
|  183         reinterpret_cast<const uint16_t*>(data_)[0] == 0xFEFF) { |  206         reinterpret_cast<const uint16_t*>(data)[0] == 0xFEFF) { | 
|  184       markup.assign(reinterpret_cast<const uint16_t*>(data_) + 1, |  207       markup.assign(reinterpret_cast<const uint16_t*>(data) + 1, | 
|  185                     (size_ / 2) - 1); |  208                     (size / 2) - 1); | 
|  186     } else { |  209     } else { | 
|  187       UTF8ToUTF16(reinterpret_cast<const char*>(data_), size_, &markup); |  210       UTF8ToUTF16(reinterpret_cast<const char*>(data), size, &markup); | 
|  188     } |  211     } | 
|  189  |  212  | 
|  190     // If there is a terminating NULL, drop it. |  213     // If there is a terminating NULL, drop it. | 
|  191     if (!markup.empty() && markup.at(markup.length() - 1) == '\0') |  214     if (!markup.empty() && markup.at(markup.length() - 1) == '\0') | 
|  192       markup.resize(markup.length() - 1); |  215       markup.resize(markup.length() - 1); | 
|  193  |  216  | 
|  194     return markup; |  217     return markup; | 
|  195   } else { |  218   } else { | 
|  196     NOTREACHED(); |  219     NOTREACHED(); | 
|  197     return markup; |  220     return markup; | 
|  198   } |  221   } | 
|  199 } |  222 } | 
|  200  |  223  | 
|  201 void SelectionData::AssignTo(std::string* result) const { |  224 void SelectionData::AssignTo(std::string* result) const { | 
|  202   result->assign(data_, size_); |  225   *result = RefCountedMemoryToString(memory_); | 
|  203 } |  226 } | 
|  204  |  227  | 
|  205 void SelectionData::AssignTo(string16* result) const { |  228 void SelectionData::AssignTo(string16* result) const { | 
|  206   result->assign(reinterpret_cast<base::char16*>(data_), size_ / 2); |  229   *result = RefCountedMemoryToString16(memory_); | 
|  207 } |  230 } | 
|  208  |  231  | 
|  209 }  // namespace ui |  232 }  // namespace ui | 
| OLD | NEW |