OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/dragdrop/os_exchange_data_provider_win.h" | 5 #include "ui/base/dragdrop/os_exchange_data_provider_win.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
(...skipping 15 matching lines...) Expand all Loading... |
26 // Creates a new STGMEDIUM object to hold the specified text. The caller | 26 // Creates a new STGMEDIUM object to hold the specified text. The caller |
27 // owns the resulting object. The "Bytes" version does not NULL terminate, the | 27 // owns the resulting object. The "Bytes" version does not NULL terminate, the |
28 // string version does. | 28 // string version does. |
29 static STGMEDIUM* GetStorageForBytes(const void* data, size_t bytes); | 29 static STGMEDIUM* GetStorageForBytes(const void* data, size_t bytes); |
30 template <typename T> | 30 template <typename T> |
31 static STGMEDIUM* GetStorageForString(const std::basic_string<T>& data); | 31 static STGMEDIUM* GetStorageForString(const std::basic_string<T>& data); |
32 // Creates the contents of an Internet Shortcut file for the given URL. | 32 // Creates the contents of an Internet Shortcut file for the given URL. |
33 static void GetInternetShortcutFileContents(const GURL& url, std::string* data); | 33 static void GetInternetShortcutFileContents(const GURL& url, std::string* data); |
34 // Creates a valid file name given a suggested title and URL. | 34 // Creates a valid file name given a suggested title and URL. |
35 static void CreateValidFileNameFromTitle(const GURL& url, | 35 static void CreateValidFileNameFromTitle(const GURL& url, |
36 const string16& title, | 36 const base::string16& title, |
37 string16* validated); | 37 base::string16* validated); |
38 // Creates a new STGMEDIUM object to hold a file. | 38 // Creates a new STGMEDIUM object to hold a file. |
39 static STGMEDIUM* GetStorageForFileName(const base::FilePath& path); | 39 static STGMEDIUM* GetStorageForFileName(const base::FilePath& path); |
40 static STGMEDIUM* GetIDListStorageForFileName(const base::FilePath& path); | 40 static STGMEDIUM* GetIDListStorageForFileName(const base::FilePath& path); |
41 // Creates a File Descriptor for the creation of a file to the given URL and | 41 // Creates a File Descriptor for the creation of a file to the given URL and |
42 // returns a handle to it. | 42 // returns a handle to it. |
43 static STGMEDIUM* GetStorageForFileDescriptor(const base::FilePath& path); | 43 static STGMEDIUM* GetStorageForFileDescriptor(const base::FilePath& path); |
44 | 44 |
45 /////////////////////////////////////////////////////////////////////////////// | 45 /////////////////////////////////////////////////////////////////////////////// |
46 // FormatEtcEnumerator | 46 // FormatEtcEnumerator |
47 | 47 |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 // Carry over | 204 // Carry over |
205 e->cursor_ = other->cursor_; | 205 e->cursor_ = other->cursor_; |
206 return e; | 206 return e; |
207 } | 207 } |
208 | 208 |
209 /////////////////////////////////////////////////////////////////////////////// | 209 /////////////////////////////////////////////////////////////////////////////// |
210 // OSExchangeDataProviderWin, public: | 210 // OSExchangeDataProviderWin, public: |
211 | 211 |
212 // static | 212 // static |
213 bool OSExchangeDataProviderWin::HasPlainTextURL(IDataObject* source) { | 213 bool OSExchangeDataProviderWin::HasPlainTextURL(IDataObject* source) { |
214 string16 plain_text; | 214 base::string16 plain_text; |
215 return (ClipboardUtil::GetPlainText(source, &plain_text) && | 215 return (ClipboardUtil::GetPlainText(source, &plain_text) && |
216 !plain_text.empty() && GURL(plain_text).is_valid()); | 216 !plain_text.empty() && GURL(plain_text).is_valid()); |
217 } | 217 } |
218 | 218 |
219 // static | 219 // static |
220 bool OSExchangeDataProviderWin::GetPlainTextURL(IDataObject* source, | 220 bool OSExchangeDataProviderWin::GetPlainTextURL(IDataObject* source, |
221 GURL* url) { | 221 GURL* url) { |
222 string16 plain_text; | 222 base::string16 plain_text; |
223 if (ClipboardUtil::GetPlainText(source, &plain_text) && | 223 if (ClipboardUtil::GetPlainText(source, &plain_text) && |
224 !plain_text.empty()) { | 224 !plain_text.empty()) { |
225 GURL gurl(plain_text); | 225 GURL gurl(plain_text); |
226 if (gurl.is_valid()) { | 226 if (gurl.is_valid()) { |
227 *url = gurl; | 227 *url = gurl; |
228 return true; | 228 return true; |
229 } | 229 } |
230 } | 230 } |
231 return false; | 231 return false; |
232 } | 232 } |
(...skipping 25 matching lines...) Expand all Loading... |
258 } | 258 } |
259 | 259 |
260 OSExchangeDataProviderWin::OSExchangeDataProviderWin() | 260 OSExchangeDataProviderWin::OSExchangeDataProviderWin() |
261 : data_(new DataObjectImpl()), | 261 : data_(new DataObjectImpl()), |
262 source_object_(data_.get()) { | 262 source_object_(data_.get()) { |
263 } | 263 } |
264 | 264 |
265 OSExchangeDataProviderWin::~OSExchangeDataProviderWin() { | 265 OSExchangeDataProviderWin::~OSExchangeDataProviderWin() { |
266 } | 266 } |
267 | 267 |
268 void OSExchangeDataProviderWin::SetString(const string16& data) { | 268 void OSExchangeDataProviderWin::SetString(const base::string16& data) { |
269 STGMEDIUM* storage = GetStorageForString(data); | 269 STGMEDIUM* storage = GetStorageForString(data); |
270 data_->contents_.push_back(new DataObjectImpl::StoredDataInfo( | 270 data_->contents_.push_back(new DataObjectImpl::StoredDataInfo( |
271 Clipboard::GetPlainTextWFormatType().ToFormatEtc(), storage)); | 271 Clipboard::GetPlainTextWFormatType().ToFormatEtc(), storage)); |
272 | 272 |
273 // Also add the UTF8-encoded version. | 273 // Also add the UTF8-encoded version. |
274 storage = GetStorageForString(UTF16ToUTF8(data)); | 274 storage = GetStorageForString(UTF16ToUTF8(data)); |
275 data_->contents_.push_back(new DataObjectImpl::StoredDataInfo( | 275 data_->contents_.push_back(new DataObjectImpl::StoredDataInfo( |
276 Clipboard::GetPlainTextFormatType().ToFormatEtc(), storage)); | 276 Clipboard::GetPlainTextFormatType().ToFormatEtc(), storage)); |
277 } | 277 } |
278 | 278 |
279 void OSExchangeDataProviderWin::SetURL(const GURL& url, | 279 void OSExchangeDataProviderWin::SetURL(const GURL& url, |
280 const string16& title) { | 280 const base::string16& title) { |
281 // NOTE WELL: | 281 // NOTE WELL: |
282 // Every time you change the order of the first two CLIPFORMATS that get | 282 // Every time you change the order of the first two CLIPFORMATS that get |
283 // added here, you need to update the EnumerationViaCOM test case in | 283 // added here, you need to update the EnumerationViaCOM test case in |
284 // the _unittest.cc file to reflect the new arrangement otherwise that test | 284 // the _unittest.cc file to reflect the new arrangement otherwise that test |
285 // will fail! It assumes an insertion order. | 285 // will fail! It assumes an insertion order. |
286 | 286 |
287 // Add text/x-moz-url for drags from Firefox | 287 // Add text/x-moz-url for drags from Firefox |
288 string16 x_moz_url_str = UTF8ToUTF16(url.spec()); | 288 base::string16 x_moz_url_str = UTF8ToUTF16(url.spec()); |
289 x_moz_url_str += '\n'; | 289 x_moz_url_str += '\n'; |
290 x_moz_url_str += title; | 290 x_moz_url_str += title; |
291 STGMEDIUM* storage = GetStorageForString(x_moz_url_str); | 291 STGMEDIUM* storage = GetStorageForString(x_moz_url_str); |
292 data_->contents_.push_back(new DataObjectImpl::StoredDataInfo( | 292 data_->contents_.push_back(new DataObjectImpl::StoredDataInfo( |
293 Clipboard::GetMozUrlFormatType().ToFormatEtc(), storage)); | 293 Clipboard::GetMozUrlFormatType().ToFormatEtc(), storage)); |
294 | 294 |
295 // Add a .URL shortcut file for dragging to Explorer. | 295 // Add a .URL shortcut file for dragging to Explorer. |
296 string16 valid_file_name; | 296 base::string16 valid_file_name; |
297 CreateValidFileNameFromTitle(url, title, &valid_file_name); | 297 CreateValidFileNameFromTitle(url, title, &valid_file_name); |
298 std::string shortcut_url_file_contents; | 298 std::string shortcut_url_file_contents; |
299 GetInternetShortcutFileContents(url, &shortcut_url_file_contents); | 299 GetInternetShortcutFileContents(url, &shortcut_url_file_contents); |
300 SetFileContents(base::FilePath(valid_file_name), shortcut_url_file_contents); | 300 SetFileContents(base::FilePath(valid_file_name), shortcut_url_file_contents); |
301 | 301 |
302 // Add a UniformResourceLocator link for apps like IE and Word. | 302 // Add a UniformResourceLocator link for apps like IE and Word. |
303 storage = GetStorageForString(UTF8ToUTF16(url.spec())); | 303 storage = GetStorageForString(UTF8ToUTF16(url.spec())); |
304 data_->contents_.push_back(new DataObjectImpl::StoredDataInfo( | 304 data_->contents_.push_back(new DataObjectImpl::StoredDataInfo( |
305 Clipboard::GetUrlWFormatType().ToFormatEtc(), storage)); | 305 Clipboard::GetUrlWFormatType().ToFormatEtc(), storage)); |
306 storage = GetStorageForString(url.spec()); | 306 storage = GetStorageForString(url.spec()); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 STGMEDIUM* storage = GetStorageForFileDescriptor(filename); | 354 STGMEDIUM* storage = GetStorageForFileDescriptor(filename); |
355 data_->contents_.push_back(new DataObjectImpl::StoredDataInfo( | 355 data_->contents_.push_back(new DataObjectImpl::StoredDataInfo( |
356 Clipboard::GetFileDescriptorFormatType().ToFormatEtc(), storage)); | 356 Clipboard::GetFileDescriptorFormatType().ToFormatEtc(), storage)); |
357 | 357 |
358 // Add CFSTR_FILECONTENTS | 358 // Add CFSTR_FILECONTENTS |
359 storage = GetStorageForBytes(file_contents.data(), file_contents.length()); | 359 storage = GetStorageForBytes(file_contents.data(), file_contents.length()); |
360 data_->contents_.push_back(new DataObjectImpl::StoredDataInfo( | 360 data_->contents_.push_back(new DataObjectImpl::StoredDataInfo( |
361 Clipboard::GetFileContentZeroFormatType().ToFormatEtc(), storage)); | 361 Clipboard::GetFileContentZeroFormatType().ToFormatEtc(), storage)); |
362 } | 362 } |
363 | 363 |
364 void OSExchangeDataProviderWin::SetHtml(const string16& html, | 364 void OSExchangeDataProviderWin::SetHtml(const base::string16& html, |
365 const GURL& base_url) { | 365 const GURL& base_url) { |
366 // Add both MS CF_HTML and text/html format. CF_HTML should be in utf-8. | 366 // Add both MS CF_HTML and text/html format. CF_HTML should be in utf-8. |
367 std::string utf8_html = UTF16ToUTF8(html); | 367 std::string utf8_html = UTF16ToUTF8(html); |
368 std::string url = base_url.is_valid() ? base_url.spec() : std::string(); | 368 std::string url = base_url.is_valid() ? base_url.spec() : std::string(); |
369 | 369 |
370 std::string cf_html = ClipboardUtil::HtmlToCFHtml(utf8_html, url); | 370 std::string cf_html = ClipboardUtil::HtmlToCFHtml(utf8_html, url); |
371 STGMEDIUM* storage = GetStorageForBytes(cf_html.c_str(), cf_html.size()); | 371 STGMEDIUM* storage = GetStorageForBytes(cf_html.c_str(), cf_html.size()); |
372 data_->contents_.push_back(new DataObjectImpl::StoredDataInfo( | 372 data_->contents_.push_back(new DataObjectImpl::StoredDataInfo( |
373 Clipboard::GetHtmlFormatType().ToFormatEtc(), storage)); | 373 Clipboard::GetHtmlFormatType().ToFormatEtc(), storage)); |
374 | 374 |
375 STGMEDIUM* storage_plain = GetStorageForBytes(utf8_html.c_str(), | 375 STGMEDIUM* storage_plain = GetStorageForBytes(utf8_html.c_str(), |
376 utf8_html.size()); | 376 utf8_html.size()); |
377 data_->contents_.push_back(new DataObjectImpl::StoredDataInfo( | 377 data_->contents_.push_back(new DataObjectImpl::StoredDataInfo( |
378 Clipboard::GetTextHtmlFormatType().ToFormatEtc(), storage_plain)); | 378 Clipboard::GetTextHtmlFormatType().ToFormatEtc(), storage_plain)); |
379 } | 379 } |
380 | 380 |
381 bool OSExchangeDataProviderWin::GetString(string16* data) const { | 381 bool OSExchangeDataProviderWin::GetString(base::string16* data) const { |
382 return ClipboardUtil::GetPlainText(source_object_, data); | 382 return ClipboardUtil::GetPlainText(source_object_, data); |
383 } | 383 } |
384 | 384 |
385 bool OSExchangeDataProviderWin::GetURLAndTitle(GURL* url, | 385 bool OSExchangeDataProviderWin::GetURLAndTitle(GURL* url, |
386 string16* title) const { | 386 base::string16* title) const { |
387 string16 url_str; | 387 base::string16 url_str; |
388 bool success = ClipboardUtil::GetUrl(source_object_, &url_str, title, true); | 388 bool success = ClipboardUtil::GetUrl(source_object_, &url_str, title, true); |
389 if (success) { | 389 if (success) { |
390 GURL test_url(url_str); | 390 GURL test_url(url_str); |
391 if (test_url.is_valid()) { | 391 if (test_url.is_valid()) { |
392 *url = test_url; | 392 *url = test_url; |
393 return true; | 393 return true; |
394 } | 394 } |
395 } else if (GetPlainTextURL(source_object_, url)) { | 395 } else if (GetPlainTextURL(source_object_, url)) { |
396 if (url->is_valid()) | 396 if (url->is_valid()) |
397 *title = net::GetSuggestedFilename(*url, "", "", "", "", std::string()); | 397 *title = net::GetSuggestedFilename(*url, "", "", "", "", std::string()); |
398 else | 398 else |
399 title->clear(); | 399 title->clear(); |
400 return true; | 400 return true; |
401 } | 401 } |
402 return false; | 402 return false; |
403 } | 403 } |
404 | 404 |
405 bool OSExchangeDataProviderWin::GetFilename(base::FilePath* path) const { | 405 bool OSExchangeDataProviderWin::GetFilename(base::FilePath* path) const { |
406 std::vector<string16> filenames; | 406 std::vector<base::string16> filenames; |
407 bool success = ClipboardUtil::GetFilenames(source_object_, &filenames); | 407 bool success = ClipboardUtil::GetFilenames(source_object_, &filenames); |
408 if (success) | 408 if (success) |
409 *path = base::FilePath(filenames[0]); | 409 *path = base::FilePath(filenames[0]); |
410 return success; | 410 return success; |
411 } | 411 } |
412 | 412 |
413 bool OSExchangeDataProviderWin::GetFilenames( | 413 bool OSExchangeDataProviderWin::GetFilenames( |
414 std::vector<OSExchangeData::FileInfo>* filenames) const { | 414 std::vector<OSExchangeData::FileInfo>* filenames) const { |
415 std::vector<string16> filenames_local; | 415 std::vector<base::string16> filenames_local; |
416 bool success = ClipboardUtil::GetFilenames(source_object_, &filenames_local); | 416 bool success = ClipboardUtil::GetFilenames(source_object_, &filenames_local); |
417 if (success) { | 417 if (success) { |
418 for (size_t i = 0; i < filenames_local.size(); ++i) | 418 for (size_t i = 0; i < filenames_local.size(); ++i) |
419 filenames->push_back( | 419 filenames->push_back( |
420 OSExchangeData::FileInfo(base::FilePath(filenames_local[i]), | 420 OSExchangeData::FileInfo(base::FilePath(filenames_local[i]), |
421 base::FilePath())); | 421 base::FilePath())); |
422 } | 422 } |
423 return success; | 423 return success; |
424 } | 424 } |
425 | 425 |
(...skipping 12 matching lines...) Expand all Loading... |
438 success = true; | 438 success = true; |
439 } | 439 } |
440 ReleaseStgMedium(&medium); | 440 ReleaseStgMedium(&medium); |
441 } | 441 } |
442 return success; | 442 return success; |
443 } | 443 } |
444 | 444 |
445 bool OSExchangeDataProviderWin::GetFileContents( | 445 bool OSExchangeDataProviderWin::GetFileContents( |
446 base::FilePath* filename, | 446 base::FilePath* filename, |
447 std::string* file_contents) const { | 447 std::string* file_contents) const { |
448 string16 filename_str; | 448 base::string16 filename_str; |
449 if (!ClipboardUtil::GetFileContents(source_object_, &filename_str, | 449 if (!ClipboardUtil::GetFileContents(source_object_, &filename_str, |
450 file_contents)) { | 450 file_contents)) { |
451 return false; | 451 return false; |
452 } | 452 } |
453 *filename = base::FilePath(filename_str); | 453 *filename = base::FilePath(filename_str); |
454 return true; | 454 return true; |
455 } | 455 } |
456 | 456 |
457 bool OSExchangeDataProviderWin::GetHtml(string16* html, | 457 bool OSExchangeDataProviderWin::GetHtml(base::string16* html, |
458 GURL* base_url) const { | 458 GURL* base_url) const { |
459 std::string url; | 459 std::string url; |
460 bool success = ClipboardUtil::GetHtml(source_object_, html, &url); | 460 bool success = ClipboardUtil::GetHtml(source_object_, html, &url); |
461 if (success) | 461 if (success) |
462 *base_url = GURL(url); | 462 *base_url = GURL(url); |
463 return success; | 463 return success; |
464 } | 464 } |
465 | 465 |
466 bool OSExchangeDataProviderWin::HasString() const { | 466 bool OSExchangeDataProviderWin::HasString() const { |
467 return ClipboardUtil::HasPlainText(source_object_); | 467 return ClipboardUtil::HasPlainText(source_object_); |
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
877 std::string* data) { | 877 std::string* data) { |
878 DCHECK(data); | 878 DCHECK(data); |
879 static const std::string kInternetShortcutFileStart = | 879 static const std::string kInternetShortcutFileStart = |
880 "[InternetShortcut]\r\nURL="; | 880 "[InternetShortcut]\r\nURL="; |
881 static const std::string kInternetShortcutFileEnd = | 881 static const std::string kInternetShortcutFileEnd = |
882 "\r\n"; | 882 "\r\n"; |
883 *data = kInternetShortcutFileStart + url.spec() + kInternetShortcutFileEnd; | 883 *data = kInternetShortcutFileStart + url.spec() + kInternetShortcutFileEnd; |
884 } | 884 } |
885 | 885 |
886 static void CreateValidFileNameFromTitle(const GURL& url, | 886 static void CreateValidFileNameFromTitle(const GURL& url, |
887 const string16& title, | 887 const base::string16& title, |
888 string16* validated) { | 888 base::string16* validated) { |
889 if (title.empty()) { | 889 if (title.empty()) { |
890 if (url.is_valid()) { | 890 if (url.is_valid()) { |
891 *validated = net::GetSuggestedFilename(url, "", "", "", "", | 891 *validated = net::GetSuggestedFilename(url, "", "", "", "", |
892 std::string()); | 892 std::string()); |
893 } else { | 893 } else { |
894 // Nothing else can be done, just use a default. | 894 // Nothing else can be done, just use a default. |
895 *validated = | 895 *validated = |
896 l10n_util::GetStringUTF16(IDS_APP_UNTITLED_SHORTCUT_FILE_NAME); | 896 l10n_util::GetStringUTF16(IDS_APP_UNTITLED_SHORTCUT_FILE_NAME); |
897 } | 897 } |
898 } else { | 898 } else { |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1001 | 1001 |
1002 STGMEDIUM* storage = new STGMEDIUM; | 1002 STGMEDIUM* storage = new STGMEDIUM; |
1003 storage->tymed = TYMED_HGLOBAL; | 1003 storage->tymed = TYMED_HGLOBAL; |
1004 storage->hGlobal = hdata; | 1004 storage->hGlobal = hdata; |
1005 storage->pUnkForRelease = NULL; | 1005 storage->pUnkForRelease = NULL; |
1006 return storage; | 1006 return storage; |
1007 } | 1007 } |
1008 | 1008 |
1009 static STGMEDIUM* GetStorageForFileDescriptor( | 1009 static STGMEDIUM* GetStorageForFileDescriptor( |
1010 const base::FilePath& path) { | 1010 const base::FilePath& path) { |
1011 string16 file_name = path.value(); | 1011 base::string16 file_name = path.value(); |
1012 DCHECK(!file_name.empty()); | 1012 DCHECK(!file_name.empty()); |
1013 HANDLE hdata = GlobalAlloc(GPTR, sizeof(FILEGROUPDESCRIPTOR)); | 1013 HANDLE hdata = GlobalAlloc(GPTR, sizeof(FILEGROUPDESCRIPTOR)); |
1014 base::win::ScopedHGlobal<FILEGROUPDESCRIPTOR> locked_mem(hdata); | 1014 base::win::ScopedHGlobal<FILEGROUPDESCRIPTOR> locked_mem(hdata); |
1015 | 1015 |
1016 FILEGROUPDESCRIPTOR* descriptor = locked_mem.get(); | 1016 FILEGROUPDESCRIPTOR* descriptor = locked_mem.get(); |
1017 descriptor->cItems = 1; | 1017 descriptor->cItems = 1; |
1018 descriptor->fgd[0].dwFlags = FD_LINKUI; | 1018 descriptor->fgd[0].dwFlags = FD_LINKUI; |
1019 wcsncpy_s(descriptor->fgd[0].cFileName, MAX_PATH, file_name.c_str(), | 1019 wcsncpy_s(descriptor->fgd[0].cFileName, MAX_PATH, file_name.c_str(), |
1020 std::min(file_name.size(), static_cast<size_t>(MAX_PATH - 1u))); | 1020 std::min(file_name.size(), static_cast<size_t>(MAX_PATH - 1u))); |
1021 | 1021 |
1022 STGMEDIUM* storage = new STGMEDIUM; | 1022 STGMEDIUM* storage = new STGMEDIUM; |
1023 storage->tymed = TYMED_HGLOBAL; | 1023 storage->tymed = TYMED_HGLOBAL; |
1024 storage->hGlobal = hdata; | 1024 storage->hGlobal = hdata; |
1025 storage->pUnkForRelease = NULL; | 1025 storage->pUnkForRelease = NULL; |
1026 return storage; | 1026 return storage; |
1027 } | 1027 } |
1028 | 1028 |
1029 /////////////////////////////////////////////////////////////////////////////// | 1029 /////////////////////////////////////////////////////////////////////////////// |
1030 // OSExchangeData, public: | 1030 // OSExchangeData, public: |
1031 | 1031 |
1032 // static | 1032 // static |
1033 OSExchangeData::Provider* OSExchangeData::CreateProvider() { | 1033 OSExchangeData::Provider* OSExchangeData::CreateProvider() { |
1034 return new OSExchangeDataProviderWin(); | 1034 return new OSExchangeDataProviderWin(); |
1035 } | 1035 } |
1036 | 1036 |
1037 } // namespace ui | 1037 } // namespace ui |
OLD | NEW |