Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(21)

Side by Side Diff: Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp

Issue 13642009: WebCore: Remove PLATFORM(WIN) files we do not use. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "config.h"
27 #include "ClipboardUtilitiesWin.h"
28
29 #include "DocumentFragment.h"
30 #include "KURL.h"
31 #include "TextEncoding.h"
32 #include "markup.h"
33 #include <shlobj.h>
34 #include <wininet.h> // for INTERNET_MAX_URL_LENGTH
35 #include <wtf/StringExtras.h>
36 #include <wtf/text/CString.h>
37 #include <wtf/text/StringBuilder.h>
38 #include <wtf/text/WTFString.h>
39
40 #if !OS(WINCE)
41 #include <shlwapi.h>
42 #endif
43
44 #if USE(CF)
45 #include <CoreFoundation/CoreFoundation.h>
46 #include <wtf/RetainPtr.h>
47 #endif
48
49 namespace WebCore {
50
51 #if USE(CF)
52 FORMATETC* cfHDropFormat()
53 {
54 static FORMATETC urlFormat = {CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOB AL};
55 return &urlFormat;
56 }
57
58 static bool urlFromPath(CFStringRef path, String& url)
59 {
60 if (!path)
61 return false;
62
63 RetainPtr<CFURLRef> cfURL(AdoptCF, CFURLCreateWithFileSystemPath(0, path, kC FURLWindowsPathStyle, false));
64 if (!cfURL)
65 return false;
66
67 url = CFURLGetString(cfURL.get());
68
69 // Work around <rdar://problem/6708300>, where CFURLCreateWithFileSystemPath makes URLs with "localhost".
70 if (url.startsWith("file://localhost/"))
71 url.remove(7, 9);
72
73 return true;
74 }
75 #endif
76
77 static bool getDataMapItem(const DragDataMap* dataObject, FORMATETC* format, Str ing& item)
78 {
79 DragDataMap::const_iterator found = dataObject->find(format->cfFormat);
80 if (found == dataObject->end())
81 return false;
82 item = found->value[0];
83 return true;
84 }
85
86 static bool getWebLocData(IDataObject* dataObject, String& url, String* title)
87 {
88 bool succeeded = false;
89 #if USE(CF)
90 WCHAR filename[MAX_PATH];
91 WCHAR urlBuffer[INTERNET_MAX_URL_LENGTH];
92
93 STGMEDIUM medium;
94 if (FAILED(dataObject->GetData(cfHDropFormat(), &medium)))
95 return false;
96
97 HDROP hdrop = static_cast<HDROP>(GlobalLock(medium.hGlobal));
98
99 if (!hdrop)
100 return false;
101
102 if (!DragQueryFileW(hdrop, 0, filename, WTF_ARRAY_LENGTH(filename)))
103 goto exit;
104
105 if (_wcsicmp(PathFindExtensionW(filename), L".url"))
106 goto exit;
107
108 if (!GetPrivateProfileStringW(L"InternetShortcut", L"url", 0, urlBuffer, WTF _ARRAY_LENGTH(urlBuffer), filename))
109 goto exit;
110
111 if (title) {
112 PathRemoveExtension(filename);
113 *title = String((UChar*)filename);
114 }
115
116 url = String((UChar*)urlBuffer);
117 succeeded = true;
118
119 exit:
120 // Free up memory.
121 DragFinish(hdrop);
122 GlobalUnlock(medium.hGlobal);
123 #endif
124 return succeeded;
125 }
126
127 static bool getWebLocData(const DragDataMap* dataObject, String& url, String* ti tle)
128 {
129 #if USE(CF)
130 WCHAR filename[MAX_PATH];
131 WCHAR urlBuffer[INTERNET_MAX_URL_LENGTH];
132
133 if (!dataObject->contains(cfHDropFormat()->cfFormat))
134 return false;
135
136 wcscpy(filename, dataObject->get(cfHDropFormat()->cfFormat)[0].charactersWit hNullTermination());
137 if (_wcsicmp(PathFindExtensionW(filename), L".url"))
138 return false;
139
140 if (!GetPrivateProfileStringW(L"InternetShortcut", L"url", 0, urlBuffer, WTF _ARRAY_LENGTH(urlBuffer), filename))
141 return false;
142
143 if (title) {
144 PathRemoveExtension(filename);
145 *title = filename;
146 }
147
148 url = urlBuffer;
149 return true;
150 #else
151 return false;
152 #endif
153 }
154
155 static String extractURL(const String &inURL, String* title)
156 {
157 String url = inURL;
158 int splitLoc = url.find('\n');
159 if (splitLoc > 0) {
160 if (title)
161 *title = url.substring(splitLoc+1);
162 url.truncate(splitLoc);
163 } else if (title)
164 *title = url;
165 return url;
166 }
167
168 // Firefox text/html
169 static FORMATETC* texthtmlFormat()
170 {
171 static UINT cf = RegisterClipboardFormat(L"text/html");
172 static FORMATETC texthtmlFormat = {cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBA L};
173 return &texthtmlFormat;
174 }
175
176 HGLOBAL createGlobalData(const KURL& url, const String& title)
177 {
178 String mutableURL(url.string());
179 String mutableTitle(title);
180 SIZE_T size = mutableURL.length() + mutableTitle.length() + 2; // +1 for "\n " and +1 for null terminator
181 HGLOBAL cbData = ::GlobalAlloc(GPTR, size * sizeof(UChar));
182
183 if (cbData) {
184 PWSTR buffer = static_cast<PWSTR>(GlobalLock(cbData));
185 _snwprintf(buffer, size, L"%s\n%s", mutableURL.charactersWithNullTermina tion(), mutableTitle.charactersWithNullTermination());
186 GlobalUnlock(cbData);
187 }
188 return cbData;
189 }
190
191 HGLOBAL createGlobalData(const String& str)
192 {
193 HGLOBAL globalData = ::GlobalAlloc(GPTR, (str.length() + 1) * sizeof(UChar)) ;
194 if (!globalData)
195 return 0;
196 UChar* buffer = static_cast<UChar*>(GlobalLock(globalData));
197 memcpy(buffer, str.characters(), str.length() * sizeof(UChar));
198 buffer[str.length()] = 0;
199 GlobalUnlock(globalData);
200 return globalData;
201 }
202
203 HGLOBAL createGlobalData(const Vector<char>& vector)
204 {
205 HGLOBAL globalData = ::GlobalAlloc(GPTR, vector.size() + 1);
206 if (!globalData)
207 return 0;
208 char* buffer = static_cast<char*>(GlobalLock(globalData));
209 memcpy(buffer, vector.data(), vector.size());
210 buffer[vector.size()] = 0;
211 GlobalUnlock(globalData);
212 return globalData;
213 }
214
215 static String getFullCFHTML(IDataObject* data)
216 {
217 STGMEDIUM store;
218 if (SUCCEEDED(data->GetData(htmlFormat(), &store))) {
219 // MS HTML Format parsing
220 char* data = static_cast<char*>(GlobalLock(store.hGlobal));
221 SIZE_T dataSize = ::GlobalSize(store.hGlobal);
222 String cfhtml(UTF8Encoding().decode(data, dataSize));
223 GlobalUnlock(store.hGlobal);
224 ReleaseStgMedium(&store);
225 return cfhtml;
226 }
227 return String();
228 }
229
230 static void append(Vector<char>& vector, const char* string)
231 {
232 vector.append(string, strlen(string));
233 }
234
235 static void append(Vector<char>& vector, const CString& string)
236 {
237 vector.append(string.data(), string.length());
238 }
239
240 // Find the markup between "<!--StartFragment -->" and "<!--EndFragment -->", ac counting for browser quirks.
241 static String extractMarkupFromCFHTML(const String& cfhtml)
242 {
243 unsigned markupStart = cfhtml.find("<html", 0, false);
244 unsigned tagStart = cfhtml.find("startfragment", markupStart, false);
245 unsigned fragmentStart = cfhtml.find('>', tagStart) + 1;
246 unsigned tagEnd = cfhtml.find("endfragment", fragmentStart, false);
247 unsigned fragmentEnd = cfhtml.reverseFind('<', tagEnd);
248 return cfhtml.substring(fragmentStart, fragmentEnd - fragmentStart).stripWhi teSpace();
249 }
250
251 // Documentation for the CF_HTML format is available at http://msdn.microsoft.co m/workshop/networking/clipboard/htmlclipboard.asp
252 void markupToCFHTML(const String& markup, const String& srcURL, Vector<char>& re sult)
253 {
254 if (markup.isEmpty())
255 return;
256
257 #define MAX_DIGITS 10
258 #define MAKE_NUMBER_FORMAT_1(digits) MAKE_NUMBER_FORMAT_2(digits)
259 #define MAKE_NUMBER_FORMAT_2(digits) "%0" #digits "u"
260 #define NUMBER_FORMAT MAKE_NUMBER_FORMAT_1(MAX_DIGITS)
261
262 const char* header = "Version:0.9\n"
263 "StartHTML:" NUMBER_FORMAT "\n"
264 "EndHTML:" NUMBER_FORMAT "\n"
265 "StartFragment:" NUMBER_FORMAT "\n"
266 "EndFragment:" NUMBER_FORMAT "\n";
267 const char* sourceURLPrefix = "SourceURL:";
268
269 const char* startMarkup = "<HTML>\n<BODY>\n<!--StartFragment-->\n";
270 const char* endMarkup = "\n<!--EndFragment-->\n</BODY>\n</HTML>";
271
272 CString sourceURLUTF8 = srcURL == blankURL() ? "" : srcURL.utf8();
273 CString markupUTF8 = markup.utf8();
274
275 // calculate offsets
276 unsigned startHTMLOffset = strlen(header) - strlen(NUMBER_FORMAT) * 4 + MAX_ DIGITS * 4;
277 if (sourceURLUTF8.length())
278 startHTMLOffset += strlen(sourceURLPrefix) + sourceURLUTF8.length() + 1;
279 unsigned startFragmentOffset = startHTMLOffset + strlen(startMarkup);
280 unsigned endFragmentOffset = startFragmentOffset + markupUTF8.length();
281 unsigned endHTMLOffset = endFragmentOffset + strlen(endMarkup);
282
283 unsigned headerBufferLength = startHTMLOffset + 1; // + 1 for '\0' terminato r.
284 char* headerBuffer = (char*)malloc(headerBufferLength);
285 snprintf(headerBuffer, headerBufferLength, header, startHTMLOffset, endHTMLO ffset, startFragmentOffset, endFragmentOffset);
286 append(result, CString(headerBuffer));
287 free(headerBuffer);
288 if (sourceURLUTF8.length()) {
289 append(result, sourceURLPrefix);
290 append(result, sourceURLUTF8);
291 result.append('\n');
292 }
293 append(result, startMarkup);
294 append(result, markupUTF8);
295 append(result, endMarkup);
296
297 #undef MAX_DIGITS
298 #undef MAKE_NUMBER_FORMAT_1
299 #undef MAKE_NUMBER_FORMAT_2
300 #undef NUMBER_FORMAT
301 }
302
303 void replaceNewlinesWithWindowsStyleNewlines(String& str)
304 {
305 DEFINE_STATIC_LOCAL(String, windowsNewline, (ASCIILiteral("\r\n")));
306 StringBuilder result;
307 for (unsigned index = 0; index < str.length(); ++index) {
308 if (str[index] != '\n' || (index > 0 && str[index - 1] == '\r'))
309 result.append(str[index]);
310 else
311 result.append(windowsNewline);
312 }
313 str = result.toString();
314 }
315
316 void replaceNBSPWithSpace(String& str)
317 {
318 static const UChar NonBreakingSpaceCharacter = 0xA0;
319 static const UChar SpaceCharacter = ' ';
320 str.replace(NonBreakingSpaceCharacter, SpaceCharacter);
321 }
322
323 FORMATETC* urlWFormat()
324 {
325 static UINT cf = RegisterClipboardFormat(L"UniformResourceLocatorW");
326 static FORMATETC urlFormat = {cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
327 return &urlFormat;
328 }
329
330 FORMATETC* urlFormat()
331 {
332 static UINT cf = RegisterClipboardFormat(L"UniformResourceLocator");
333 static FORMATETC urlFormat = {cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
334 return &urlFormat;
335 }
336
337 FORMATETC* plainTextFormat()
338 {
339 static FORMATETC textFormat = {CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOB AL};
340 return &textFormat;
341 }
342
343 FORMATETC* plainTextWFormat()
344 {
345 static FORMATETC textFormat = {CF_UNICODETEXT, 0, DVASPECT_CONTENT, -1, TYME D_HGLOBAL};
346 return &textFormat;
347 }
348
349 FORMATETC* filenameWFormat()
350 {
351 static UINT cf = RegisterClipboardFormat(L"FileNameW");
352 static FORMATETC urlFormat = {cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
353 return &urlFormat;
354 }
355
356 FORMATETC* filenameFormat()
357 {
358 static UINT cf = RegisterClipboardFormat(L"FileName");
359 static FORMATETC urlFormat = {cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
360 return &urlFormat;
361 }
362
363 // MSIE HTML Format
364 FORMATETC* htmlFormat()
365 {
366 static UINT cf = RegisterClipboardFormat(L"HTML Format");
367 static FORMATETC htmlFormat = {cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
368 return &htmlFormat;
369 }
370
371 FORMATETC* smartPasteFormat()
372 {
373 static UINT cf = RegisterClipboardFormat(L"WebKit Smart Paste Format");
374 static FORMATETC htmlFormat = {cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
375 return &htmlFormat;
376 }
377
378 FORMATETC* fileDescriptorFormat()
379 {
380 static UINT cf = RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR);
381 static FORMATETC fileDescriptorFormat = { cf, 0, DVASPECT_CONTENT, -1, TYMED _HGLOBAL };
382 return &fileDescriptorFormat;
383 }
384
385 FORMATETC* fileContentFormatZero()
386 {
387 static UINT cf = RegisterClipboardFormat(CFSTR_FILECONTENTS);
388 static FORMATETC fileContentFormat = { cf, 0, DVASPECT_CONTENT, 0, TYMED_HGL OBAL };
389 return &fileContentFormat;
390 }
391
392 void getFileDescriptorData(IDataObject* dataObject, int& size, String& pathname)
393 {
394 STGMEDIUM store;
395 size = 0;
396 if (FAILED(dataObject->GetData(fileDescriptorFormat(), &store)))
397 return;
398
399 FILEGROUPDESCRIPTOR* fgd = static_cast<FILEGROUPDESCRIPTOR*>(GlobalLock(stor e.hGlobal));
400 size = fgd->fgd[0].nFileSizeLow;
401 pathname = fgd->fgd[0].cFileName;
402
403 GlobalUnlock(store.hGlobal);
404 ::ReleaseStgMedium(&store);
405 }
406
407 void getFileContentData(IDataObject* dataObject, int size, void* dataBlob)
408 {
409 STGMEDIUM store;
410 if (FAILED(dataObject->GetData(fileContentFormatZero(), &store)))
411 return;
412 void* data = GlobalLock(store.hGlobal);
413 ::CopyMemory(dataBlob, data, size);
414
415 GlobalUnlock(store.hGlobal);
416 ::ReleaseStgMedium(&store);
417 }
418
419 void setFileDescriptorData(IDataObject* dataObject, int size, const String& pass edPathname)
420 {
421 String pathname = passedPathname;
422
423 STGMEDIUM medium = { 0 };
424 medium.tymed = TYMED_HGLOBAL;
425
426 medium.hGlobal = ::GlobalAlloc(GPTR, sizeof(FILEGROUPDESCRIPTOR));
427 if (!medium.hGlobal)
428 return;
429
430 FILEGROUPDESCRIPTOR* fgd = static_cast<FILEGROUPDESCRIPTOR*>(GlobalLock(medi um.hGlobal));
431 ::ZeroMemory(fgd, sizeof(FILEGROUPDESCRIPTOR));
432 fgd->cItems = 1;
433 fgd->fgd[0].dwFlags = FD_FILESIZE;
434 fgd->fgd[0].nFileSizeLow = size;
435
436 int maxSize = std::min<int>(pathname.length(), WTF_ARRAY_LENGTH(fgd->fgd[0]. cFileName));
437 CopyMemory(fgd->fgd[0].cFileName, pathname.charactersWithNullTermination(), maxSize * sizeof(UChar));
438 GlobalUnlock(medium.hGlobal);
439
440 dataObject->SetData(fileDescriptorFormat(), &medium, TRUE);
441 }
442
443 void setFileContentData(IDataObject* dataObject, int size, void* dataBlob)
444 {
445 STGMEDIUM medium = { 0 };
446 medium.tymed = TYMED_HGLOBAL;
447
448 medium.hGlobal = ::GlobalAlloc(GPTR, size);
449 if (!medium.hGlobal)
450 return;
451 void* fileContents = GlobalLock(medium.hGlobal);
452 ::CopyMemory(fileContents, dataBlob, size);
453 GlobalUnlock(medium.hGlobal);
454
455 dataObject->SetData(fileContentFormatZero(), &medium, TRUE);
456 }
457
458 String getURL(IDataObject* dataObject, DragData::FilenameConversionPolicy filena mePolicy, String* title)
459 {
460 STGMEDIUM store;
461 String url;
462 if (getWebLocData(dataObject, url, title))
463 return url;
464
465 if (SUCCEEDED(dataObject->GetData(urlWFormat(), &store))) {
466 // URL using Unicode
467 UChar* data = static_cast<UChar*>(GlobalLock(store.hGlobal));
468 url = extractURL(String(data), title);
469 GlobalUnlock(store.hGlobal);
470 ReleaseStgMedium(&store);
471 } else if (SUCCEEDED(dataObject->GetData(urlFormat(), &store))) {
472 // URL using ASCII
473 char* data = static_cast<char*>(GlobalLock(store.hGlobal));
474 url = extractURL(String(data), title);
475 GlobalUnlock(store.hGlobal);
476 ReleaseStgMedium(&store);
477 }
478 #if USE(CF)
479 else if (filenamePolicy == DragData::ConvertFilenames) {
480 if (SUCCEEDED(dataObject->GetData(filenameWFormat(), &store))) {
481 // file using unicode
482 wchar_t* data = static_cast<wchar_t*>(GlobalLock(store.hGlobal));
483 if (data && data[0] && (PathFileExists(data) || PathIsUNC(data))) {
484 RetainPtr<CFStringRef> pathAsCFString(AdoptCF, CFStringCreateWit hCharacters(kCFAllocatorDefault, (const UniChar*)data, wcslen(data)));
485 if (urlFromPath(pathAsCFString.get(), url) && title)
486 *title = url;
487 }
488 GlobalUnlock(store.hGlobal);
489 ReleaseStgMedium(&store);
490 } else if (SUCCEEDED(dataObject->GetData(filenameFormat(), &store))) {
491 // filename using ascii
492 char* data = static_cast<char*>(GlobalLock(store.hGlobal));
493 if (data && data[0] && (PathFileExistsA(data) || PathIsUNCA(data))) {
494 RetainPtr<CFStringRef> pathAsCFString(AdoptCF, CFStringCreateWit hCString(kCFAllocatorDefault, data, kCFStringEncodingASCII));
495 if (urlFromPath(pathAsCFString.get(), url) && title)
496 *title = url;
497 }
498 GlobalUnlock(store.hGlobal);
499 ReleaseStgMedium(&store);
500 }
501 }
502 #endif
503 return url;
504 }
505
506 String getURL(const DragDataMap* data, DragData::FilenameConversionPolicy filena mePolicy, String* title)
507 {
508 String url;
509
510 if (getWebLocData(data, url, title))
511 return url;
512 if (getDataMapItem(data, urlWFormat(), url))
513 return extractURL(url, title);
514 if (getDataMapItem(data, urlFormat(), url))
515 return extractURL(url, title);
516 #if USE(CF)
517 if (filenamePolicy != DragData::ConvertFilenames)
518 return url;
519
520 String stringData;
521 if (!getDataMapItem(data, filenameWFormat(), stringData))
522 getDataMapItem(data, filenameFormat(), stringData);
523
524 if (stringData.isEmpty() || (!PathFileExists(stringData.charactersWithNullTe rmination()) && !PathIsUNC(stringData.charactersWithNullTermination())))
525 return url;
526 RetainPtr<CFStringRef> pathAsCFString(AdoptCF, CFStringCreateWithCharacters( kCFAllocatorDefault, (const UniChar *)stringData.charactersWithNullTermination() , wcslen(stringData.charactersWithNullTermination())));
527 if (urlFromPath(pathAsCFString.get(), url) && title)
528 *title = url;
529 #endif
530 return url;
531 }
532
533 String getPlainText(IDataObject* dataObject)
534 {
535 STGMEDIUM store;
536 String text;
537 if (SUCCEEDED(dataObject->GetData(plainTextWFormat(), &store))) {
538 // Unicode text
539 UChar* data = static_cast<UChar*>(GlobalLock(store.hGlobal));
540 text = String(data);
541 GlobalUnlock(store.hGlobal);
542 ReleaseStgMedium(&store);
543 } else if (SUCCEEDED(dataObject->GetData(plainTextFormat(), &store))) {
544 // ASCII text
545 char* data = static_cast<char*>(GlobalLock(store.hGlobal));
546 text = String(data);
547 GlobalUnlock(store.hGlobal);
548 ReleaseStgMedium(&store);
549 } else {
550 // FIXME: Originally, we called getURL() here because dragging and dropp ing files doesn't
551 // populate the drag with text data. Per https://bugs.webkit.org/show_bu g.cgi?id=38826, this
552 // is undesirable, so maybe this line can be removed.
553 text = getURL(dataObject, DragData::DoNotConvertFilenames);
554 }
555 return text;
556 }
557
558 String getPlainText(const DragDataMap* data)
559 {
560 String text;
561
562 if (getDataMapItem(data, plainTextWFormat(), text))
563 return text;
564 if (getDataMapItem(data, plainTextFormat(), text))
565 return text;
566 return getURL(data, DragData::DoNotConvertFilenames);
567 }
568
569 String getTextHTML(IDataObject* data)
570 {
571 STGMEDIUM store;
572 String html;
573 if (SUCCEEDED(data->GetData(texthtmlFormat(), &store))) {
574 UChar* data = static_cast<UChar*>(GlobalLock(store.hGlobal));
575 html = String(data);
576 GlobalUnlock(store.hGlobal);
577 ReleaseStgMedium(&store);
578 }
579 return html;
580 }
581
582 String getTextHTML(const DragDataMap* data)
583 {
584 String text;
585 getDataMapItem(data, texthtmlFormat(), text);
586 return text;
587 }
588
589 String getCFHTML(IDataObject* data)
590 {
591 String cfhtml = getFullCFHTML(data);
592 if (!cfhtml.isEmpty())
593 return extractMarkupFromCFHTML(cfhtml);
594 return String();
595 }
596
597 String getCFHTML(const DragDataMap* dataMap)
598 {
599 String cfhtml;
600 getDataMapItem(dataMap, htmlFormat(), cfhtml);
601 return extractMarkupFromCFHTML(cfhtml);
602 }
603
604 PassRefPtr<DocumentFragment> fragmentFromFilenames(Document*, const IDataObject* )
605 {
606 // FIXME: We should be able to create fragments from files
607 return 0;
608 }
609
610 PassRefPtr<DocumentFragment> fragmentFromFilenames(Document*, const DragDataMap* )
611 {
612 // FIXME: We should be able to create fragments from files
613 return 0;
614 }
615
616 bool containsFilenames(const IDataObject*)
617 {
618 // FIXME: We'll want to update this once we can produce fragments from files
619 return false;
620 }
621
622 bool containsFilenames(const DragDataMap*)
623 {
624 // FIXME: We'll want to update this once we can produce fragments from files
625 return false;
626 }
627
628 // Convert a String containing CF_HTML formatted text to a DocumentFragment
629 PassRefPtr<DocumentFragment> fragmentFromCFHTML(Document* doc, const String& cfh tml)
630 {
631 // obtain baseURL if present
632 String srcURLStr("sourceURL:");
633 String srcURL;
634 unsigned lineStart = cfhtml.find(srcURLStr, 0, false);
635 if (lineStart != -1) {
636 unsigned srcEnd = cfhtml.find("\n", lineStart, false);
637 unsigned srcStart = lineStart+srcURLStr.length();
638 String rawSrcURL = cfhtml.substring(srcStart, srcEnd-srcStart);
639 replaceNBSPWithSpace(rawSrcURL);
640 srcURL = rawSrcURL.stripWhiteSpace();
641 }
642
643 String markup = extractMarkupFromCFHTML(cfhtml);
644 return createFragmentFromMarkup(doc, markup, srcURL, DisallowScriptingAndPlu ginContent);
645 }
646
647 PassRefPtr<DocumentFragment> fragmentFromHTML(Document* doc, IDataObject* data)
648 {
649 if (!doc || !data)
650 return 0;
651
652 String cfhtml = getFullCFHTML(data);
653 if (!cfhtml.isEmpty()) {
654 if (RefPtr<DocumentFragment> fragment = fragmentFromCFHTML(doc, cfhtml))
655 return fragment.release();
656 }
657
658 String html = getTextHTML(data);
659 String srcURL;
660 if (!html.isEmpty())
661 return createFragmentFromMarkup(doc, html, srcURL, DisallowScriptingAndP luginContent);
662
663 return 0;
664 }
665
666 PassRefPtr<DocumentFragment> fragmentFromHTML(Document* document, const DragData Map* data)
667 {
668 if (!document || !data || data->isEmpty())
669 return 0;
670
671 String stringData;
672 if (getDataMapItem(data, htmlFormat(), stringData)) {
673 if (RefPtr<DocumentFragment> fragment = fragmentFromCFHTML(document, str ingData))
674 return fragment.release();
675 }
676
677 String srcURL;
678 if (getDataMapItem(data, texthtmlFormat(), stringData))
679 return createFragmentFromMarkup(document, stringData, srcURL, DisallowSc riptingAndPluginContent);
680
681 return 0;
682 }
683
684 bool containsHTML(IDataObject* data)
685 {
686 return SUCCEEDED(data->QueryGetData(texthtmlFormat())) || SUCCEEDED(data->Qu eryGetData(htmlFormat()));
687 }
688
689 bool containsHTML(const DragDataMap* data)
690 {
691 return data->contains(texthtmlFormat()->cfFormat) || data->contains(htmlForm at()->cfFormat);
692 }
693
694 typedef void (*GetStringFunction)(IDataObject*, FORMATETC*, Vector<String>&);
695 typedef void (*SetStringFunction)(IDataObject*, FORMATETC*, const Vector<String> &);
696
697 struct ClipboardDataItem {
698 GetStringFunction getString;
699 SetStringFunction setString;
700 FORMATETC* format;
701
702 ClipboardDataItem(FORMATETC* format, GetStringFunction getString, SetStringF unction setString): format(format), getString(getString), setString(setString) { }
703 };
704
705 typedef HashMap<UINT, ClipboardDataItem*> ClipboardFormatMap;
706
707 // Getter functions.
708
709 template<typename T> void getStringData(IDataObject* data, FORMATETC* format, Ve ctor<String>& dataStrings)
710 {
711 STGMEDIUM store;
712 if (FAILED(data->GetData(format, &store)))
713 return;
714 dataStrings.append(String(static_cast<T*>(GlobalLock(store.hGlobal)), ::Glob alSize(store.hGlobal) / sizeof(T)));
715 GlobalUnlock(store.hGlobal);
716 ReleaseStgMedium(&store);
717 }
718
719 void getUtf8Data(IDataObject* data, FORMATETC* format, Vector<String>& dataStrin gs)
720 {
721 STGMEDIUM store;
722 if (FAILED(data->GetData(format, &store)))
723 return;
724 dataStrings.append(String(UTF8Encoding().decode(static_cast<char*>(GlobalLoc k(store.hGlobal)), GlobalSize(store.hGlobal))));
725 GlobalUnlock(store.hGlobal);
726 ReleaseStgMedium(&store);
727 }
728
729 #if USE(CF)
730 void getCFData(IDataObject* data, FORMATETC* format, Vector<String>& dataStrings )
731 {
732 STGMEDIUM store;
733 if (FAILED(data->GetData(format, &store)))
734 return;
735
736 HDROP hdrop = reinterpret_cast<HDROP>(GlobalLock(store.hGlobal));
737 if (!hdrop)
738 return;
739
740 WCHAR filename[MAX_PATH];
741 UINT fileCount = DragQueryFileW(hdrop, 0xFFFFFFFF, 0, 0);
742 for (UINT i = 0; i < fileCount; i++) {
743 if (!DragQueryFileW(hdrop, i, filename, WTF_ARRAY_LENGTH(filename)))
744 continue;
745 dataStrings.append(static_cast<UChar*>(filename));
746 }
747
748 GlobalUnlock(store.hGlobal);
749 ReleaseStgMedium(&store);
750 }
751 #endif
752
753 // Setter functions.
754
755 void setUCharData(IDataObject* data, FORMATETC* format, const Vector<String>& da taStrings)
756 {
757 STGMEDIUM medium = {0};
758 medium.tymed = TYMED_HGLOBAL;
759
760 medium.hGlobal = createGlobalData(dataStrings.first());
761 if (!medium.hGlobal)
762 return;
763 data->SetData(format, &medium, FALSE);
764 ::GlobalFree(medium.hGlobal);
765 }
766
767 void setUtf8Data(IDataObject* data, FORMATETC* format, const Vector<String>& dat aStrings)
768 {
769 STGMEDIUM medium = {0};
770 medium.tymed = TYMED_HGLOBAL;
771
772 CString charString = dataStrings.first().utf8();
773 size_t stringLength = charString.length();
774 medium.hGlobal = ::GlobalAlloc(GPTR, stringLength + 1);
775 if (!medium.hGlobal)
776 return;
777 char* buffer = static_cast<char*>(GlobalLock(medium.hGlobal));
778 memcpy(buffer, charString.data(), stringLength);
779 buffer[stringLength] = 0;
780 GlobalUnlock(medium.hGlobal);
781 data->SetData(format, &medium, FALSE);
782 ::GlobalFree(medium.hGlobal);
783 }
784
785 #if USE(CF)
786 void setCFData(IDataObject* data, FORMATETC* format, const Vector<String>& dataS trings)
787 {
788 STGMEDIUM medium = {0};
789 medium.tymed = TYMED_HGLOBAL;
790
791 SIZE_T dropFilesSize = sizeof(DROPFILES) + (sizeof(WCHAR) * (dataStrings.fir st().length() + 2));
792 medium.hGlobal = ::GlobalAlloc(GHND | GMEM_SHARE, dropFilesSize);
793 if (!medium.hGlobal)
794 return;
795
796 DROPFILES* dropFiles = reinterpret_cast<DROPFILES *>(GlobalLock(medium.hGlob al));
797 dropFiles->pFiles = sizeof(DROPFILES);
798 dropFiles->fWide = TRUE;
799 String filename = dataStrings.first();
800 wcscpy(reinterpret_cast<LPWSTR>(dropFiles + 1), filename.charactersWithNullT ermination());
801 GlobalUnlock(medium.hGlobal);
802 data->SetData(format, &medium, FALSE);
803 ::GlobalFree(medium.hGlobal);
804 }
805 #endif
806
807 static const ClipboardFormatMap& getClipboardMap()
808 {
809 static ClipboardFormatMap formatMap;
810 if (formatMap.isEmpty()) {
811 formatMap.add(htmlFormat()->cfFormat, new ClipboardDataItem(htmlFormat() , getUtf8Data, setUtf8Data));
812 formatMap.add(texthtmlFormat()->cfFormat, new ClipboardDataItem(texthtml Format(), getStringData<UChar>, setUCharData));
813 formatMap.add(plainTextFormat()->cfFormat, new ClipboardDataItem(plainT extFormat(), getStringData<char>, setUtf8Data));
814 formatMap.add(plainTextWFormat()->cfFormat, new ClipboardDataItem(plain TextWFormat(), getStringData<UChar>, setUCharData));
815 #if USE(CF)
816 formatMap.add(cfHDropFormat()->cfFormat, new ClipboardDataItem(cfHDropF ormat(), getCFData, setCFData));
817 #endif
818 formatMap.add(filenameFormat()->cfFormat, new ClipboardDataItem(filenam eFormat(), getStringData<char>, setUtf8Data));
819 formatMap.add(filenameWFormat()->cfFormat, new ClipboardDataItem(filena meWFormat(), getStringData<UChar>, setUCharData));
820 formatMap.add(urlFormat()->cfFormat, new ClipboardDataItem(urlFormat(), getStringData<char>, setUtf8Data));
821 formatMap.add(urlWFormat()->cfFormat, new ClipboardDataItem(urlWFormat( ), getStringData<UChar>, setUCharData));
822 }
823 return formatMap;
824 }
825
826 void getClipboardData(IDataObject* dataObject, FORMATETC* format, Vector<String> & dataStrings)
827 {
828 const ClipboardFormatMap& formatMap = getClipboardMap();
829 ClipboardFormatMap::const_iterator found = formatMap.find(format->cfFormat);
830 if (found == formatMap.end())
831 return;
832 found->value->getString(dataObject, found->value->format, dataStrings);
833 }
834
835 void setClipboardData(IDataObject* dataObject, UINT format, const Vector<String> & dataStrings)
836 {
837 const ClipboardFormatMap& formatMap = getClipboardMap();
838 ClipboardFormatMap::const_iterator found = formatMap.find(format);
839 if (found == formatMap.end())
840 return;
841 found->value->setString(dataObject, found->value->format, dataStrings);
842 }
843
844 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/WebCore/platform/win/ClipboardUtilitiesWin.h ('k') | Source/WebCore/platform/win/ClipboardWin.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698