4 * Copyright 1994 Martin Ayotte
7 * 2003 Ulrich Czekalla for CodeWeavers
8 * Copyright 2011, 2012, 2013 Ken Thomases for CodeWeavers Inc.
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
31 #include "wine/list.h"
32 #include "wine/server.h"
33 #include "wine/unicode.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(clipboard);
39 /**************************************************************************
41 **************************************************************************/
47 } CLIPBOARDINFO, *LPCLIPBOARDINFO;
49 typedef HANDLE (*DRVIMPORTFUNC)(CFDataRef data);
50 typedef CFDataRef (*DRVEXPORTFUNC)(HANDLE data);
57 DRVIMPORTFUNC import_func;
58 DRVEXPORTFUNC export_func;
63 /**************************************************************************
65 **************************************************************************/
68 /**************************************************************************
69 * Forward Function Declarations
70 **************************************************************************/
72 static HANDLE import_clipboard_data(CFDataRef data);
73 static HANDLE import_bmp_to_bitmap(CFDataRef data);
74 static HANDLE import_bmp_to_dib(CFDataRef data);
75 static HANDLE import_nsfilenames_to_hdrop(CFDataRef data);
76 static HANDLE import_oemtext_to_text(CFDataRef data);
77 static HANDLE import_oemtext_to_unicodetext(CFDataRef data);
78 static HANDLE import_text_to_oemtext(CFDataRef data);
79 static HANDLE import_text_to_unicodetext(CFDataRef data);
80 static HANDLE import_unicodetext_to_oemtext(CFDataRef data);
81 static HANDLE import_unicodetext_to_text(CFDataRef data);
82 static HANDLE import_utf8_to_oemtext(CFDataRef data);
83 static HANDLE import_utf8_to_text(CFDataRef data);
84 static HANDLE import_utf8_to_unicodetext(CFDataRef data);
86 static CFDataRef export_clipboard_data(HANDLE data);
87 static CFDataRef export_bitmap_to_bmp(HANDLE data);
88 static CFDataRef export_dib_to_bmp(HANDLE data);
89 static CFDataRef export_hdrop_to_filenames(HANDLE data);
90 static CFDataRef export_oemtext_to_utf8(HANDLE data);
91 static CFDataRef export_text_to_utf8(HANDLE data);
92 static CFDataRef export_unicodetext_to_utf8(HANDLE data);
95 /**************************************************************************
97 **************************************************************************/
99 /* Clipboard formats */
100 static struct list format_list = LIST_INIT(format_list);
102 /* There are two naming schemes involved and we want to have a mapping between
103 them. There are Win32 clipboard format names and there are Mac pasteboard
106 The Win32 standard clipboard formats don't have names, but they are associated
107 with Mac pasteboard types through the following tables, which are used to
108 initialize the format_list. Where possible, the standard clipboard formats
109 are mapped to predefined pasteboard type UTIs. Otherwise, we create Wine-
110 specific types of the form "org.winehq.builtin.<format>", where <format> is
111 the name of the symbolic constant for the format minus "CF_" and lowercased.
112 E.g. CF_BITMAP -> org.winehq.builtin.bitmap.
114 Win32 clipboard formats which originate in a Windows program may be registered
115 with an arbitrary name. We construct a Mac pasteboard type from these by
116 prepending "org.winehq.registered." to the registered name.
118 Likewise, Mac pasteboard types which originate in other apps may have
119 arbitrary type strings. We construct a Win32 clipboard format name from
120 these by prepending "org.winehq.mac-type." to the Mac pasteboard type.
123 Win32 clipboard format names:
124 <none> standard clipboard format; maps via
125 format_list to either a predefined Mac UTI
126 or org.winehq.builtin.<format>.
127 org.winehq.mac-type.<Mac type> representation of Mac type in Win32 land;
129 <other> name registered within Win32 land; maps to
130 org.winehq.registered.<other>
131 Mac pasteboard type names:
132 org.winehq.builtin.<format ID> representation of Win32 standard clipboard
133 format for which there was no corresponding
134 predefined Mac UTI; maps via format_list
135 org.winehq.registered.<format name> representation of Win32 registered
136 clipboard format name; maps to <format name>
137 <other> Mac pasteboard type originating with system
138 or other apps; either maps via format_list
139 to a standard clipboard format or maps to
140 org.winehq.mac-type.<other>
147 DRVIMPORTFUNC import;
148 DRVEXPORTFUNC export;
150 } builtin_format_ids[] =
152 { CF_DIBV5, CFSTR("org.winehq.builtin.dibv5"), import_clipboard_data, export_clipboard_data, FALSE },
153 { CF_DIF, CFSTR("org.winehq.builtin.dif"), import_clipboard_data, export_clipboard_data, FALSE },
154 { CF_DSPBITMAP, CFSTR("org.winehq.builtin.dspbitmap"), import_clipboard_data, export_clipboard_data, FALSE },
155 { CF_DSPENHMETAFILE, CFSTR("org.winehq.builtin.dspenhmetafile"), import_clipboard_data, export_clipboard_data, FALSE },
156 { CF_DSPMETAFILEPICT, CFSTR("org.winehq.builtin.dspmetafilepict"), import_clipboard_data, export_clipboard_data, FALSE },
157 { CF_DSPTEXT, CFSTR("org.winehq.builtin.dsptext"), import_clipboard_data, export_clipboard_data, FALSE },
158 { CF_LOCALE, CFSTR("org.winehq.builtin.locale"), import_clipboard_data, export_clipboard_data, FALSE },
159 { CF_OWNERDISPLAY, CFSTR("org.winehq.builtin.ownerdisplay"), import_clipboard_data, export_clipboard_data, FALSE },
160 { CF_PALETTE, CFSTR("org.winehq.builtin.palette"), import_clipboard_data, export_clipboard_data, FALSE },
161 { CF_PENDATA, CFSTR("org.winehq.builtin.pendata"), import_clipboard_data, export_clipboard_data, FALSE },
162 { CF_RIFF, CFSTR("org.winehq.builtin.riff"), import_clipboard_data, export_clipboard_data, FALSE },
163 { CF_SYLK, CFSTR("org.winehq.builtin.sylk"), import_clipboard_data, export_clipboard_data, FALSE },
164 { CF_TIFF, CFSTR("public.tiff"), import_clipboard_data, export_clipboard_data, FALSE },
165 { CF_WAVE, CFSTR("com.microsoft.waveform-audio"), import_clipboard_data, export_clipboard_data, FALSE },
167 { CF_UNICODETEXT, CFSTR("org.winehq.builtin.unicodetext"), import_clipboard_data, export_clipboard_data, FALSE },
168 { CF_TEXT, CFSTR("org.winehq.builtin.unicodetext"), import_unicodetext_to_text, NULL, TRUE },
169 { CF_OEMTEXT, CFSTR("org.winehq.builtin.unicodetext"), import_unicodetext_to_oemtext, NULL, TRUE },
171 { CF_TEXT, CFSTR("org.winehq.builtin.text"), import_clipboard_data, export_clipboard_data, FALSE },
172 { CF_UNICODETEXT, CFSTR("org.winehq.builtin.text"), import_text_to_unicodetext, NULL, TRUE },
173 { CF_OEMTEXT, CFSTR("org.winehq.builtin.text"), import_text_to_oemtext, NULL, TRUE },
175 { CF_OEMTEXT, CFSTR("org.winehq.builtin.oemtext"), import_clipboard_data, export_clipboard_data, FALSE },
176 { CF_UNICODETEXT, CFSTR("org.winehq.builtin.oemtext"), import_oemtext_to_unicodetext, NULL, TRUE },
177 { CF_TEXT, CFSTR("org.winehq.builtin.oemtext"), import_oemtext_to_text, NULL, TRUE },
179 { CF_UNICODETEXT, CFSTR("public.utf8-plain-text"), import_utf8_to_unicodetext, export_unicodetext_to_utf8, TRUE },
180 { CF_TEXT, CFSTR("public.utf8-plain-text"), import_utf8_to_text, export_text_to_utf8, TRUE },
181 { CF_OEMTEXT, CFSTR("public.utf8-plain-text"), import_utf8_to_oemtext, export_oemtext_to_utf8, TRUE },
183 { CF_DIB, CFSTR("org.winehq.builtin.dib"), import_clipboard_data, export_clipboard_data, FALSE },
184 { CF_DIB, CFSTR("com.microsoft.bmp"), import_bmp_to_dib, export_dib_to_bmp, TRUE },
186 { CF_BITMAP, CFSTR("org.winehq.builtin.bitmap"), import_bmp_to_bitmap, export_bitmap_to_bmp, FALSE },
187 { CF_BITMAP, CFSTR("com.microsoft.bmp"), import_bmp_to_bitmap, export_bitmap_to_bmp, TRUE },
189 { CF_HDROP, CFSTR("org.winehq.builtin.hdrop"), import_clipboard_data, export_clipboard_data, FALSE },
190 { CF_HDROP, CFSTR("NSFilenamesPboardType"), import_nsfilenames_to_hdrop, export_hdrop_to_filenames, TRUE },
193 static const WCHAR wszRichTextFormat[] = {'R','i','c','h',' ','T','e','x','t',' ','F','o','r','m','a','t',0};
194 static const WCHAR wszGIF[] = {'G','I','F',0};
195 static const WCHAR wszJFIF[] = {'J','F','I','F',0};
196 static const WCHAR wszPNG[] = {'P','N','G',0};
197 static const WCHAR wszHTMLFormat[] = {'H','T','M','L',' ','F','o','r','m','a','t',0};
202 } builtin_format_names[] =
204 { wszRichTextFormat, CFSTR("public.rtf") },
205 { wszGIF, CFSTR("com.compuserve.gif") },
206 { wszJFIF, CFSTR("public.jpeg") },
207 { wszPNG, CFSTR("public.png") },
208 { wszHTMLFormat, CFSTR("public.html") },
211 /* The prefix prepended to an external Mac pasteboard type to make a Win32 clipboard format name. org.winehq.mac-type. */
212 static const WCHAR mac_type_name_prefix[] = {'o','r','g','.','w','i','n','e','h','q','.','m','a','c','-','t','y','p','e','.',0};
214 /* The prefix prepended to a Win32 clipboard format name to make a Mac pasteboard type. */
215 static const CFStringRef registered_name_type_prefix = CFSTR("org.winehq.registered.");
218 /**************************************************************************
219 * Internal Clipboard implementation methods
220 **************************************************************************/
223 * format_list functions
226 /**************************************************************************
229 static const char *debugstr_format(UINT id)
233 if (GetClipboardFormatNameW(id, buffer, 256))
234 return wine_dbg_sprintf("0x%04x %s", id, debugstr_w(buffer));
238 #define BUILTIN(id) case id: return #id;
241 BUILTIN(CF_METAFILEPICT)
251 BUILTIN(CF_UNICODETEXT)
252 BUILTIN(CF_ENHMETAFILE)
256 BUILTIN(CF_OWNERDISPLAY)
258 BUILTIN(CF_DSPBITMAP)
259 BUILTIN(CF_DSPMETAFILEPICT)
260 BUILTIN(CF_DSPENHMETAFILE)
262 default: return wine_dbg_sprintf("0x%04x", id);
267 /**************************************************************************
268 * insert_clipboard_format
270 static WINE_CLIPFORMAT *insert_clipboard_format(UINT id, CFStringRef type)
272 WINE_CLIPFORMAT *format;
274 format = HeapAlloc(GetProcessHeap(), 0, sizeof(*format));
278 WARN("No more memory for a new format!\n");
281 format->format_id = id;
282 format->import_func = import_clipboard_data;
283 format->export_func = export_clipboard_data;
284 format->synthesized = FALSE;
287 format->type = CFStringCreateCopy(NULL, type);
292 GetClipboardFormatNameW(format->format_id, buffer, 256);
293 if (!strncmpW(buffer, mac_type_name_prefix, strlenW(mac_type_name_prefix)))
295 const WCHAR *p = buffer + strlenW(mac_type_name_prefix);
296 format->type = CFStringCreateWithCharacters(NULL, (UniChar*)p, strlenW(p));
300 format->type = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%S"),
301 registered_name_type_prefix, buffer);
305 list_add_tail(&format_list, &format->entry);
307 TRACE("Registering format %s type %s\n", debugstr_format(format->format_id),
308 debugstr_cf(format->type));
314 /**************************************************************************
317 * Register a custom Mac clipboard format.
319 static WINE_CLIPFORMAT* register_format(UINT id, CFStringRef type)
321 WINE_CLIPFORMAT *format;
323 /* walk format chain to see if it's already registered */
324 LIST_FOR_EACH_ENTRY(format, &format_list, WINE_CLIPFORMAT, entry)
325 if (format->format_id == id) return format;
327 return insert_clipboard_format(id, type);
331 /**************************************************************************
334 static WINE_CLIPFORMAT* format_for_type(WINE_CLIPFORMAT *current, CFStringRef type)
336 struct list *ptr = current ? ¤t->entry : &format_list;
337 WINE_CLIPFORMAT *format = NULL;
339 TRACE("current %p/%s type %s\n", current, debugstr_format(current ? current->format_id : 0), debugstr_cf(type));
341 while ((ptr = list_next(&format_list, ptr)))
343 format = LIST_ENTRY(ptr, WINE_CLIPFORMAT, entry);
344 if (CFEqual(format->type, type))
346 TRACE(" -> %p/%s\n", format, debugstr_format(format->format_id));
355 if (CFStringHasPrefix(type, CFSTR("org.winehq.builtin.")))
357 ERR("Shouldn't happen. Built-in type %s should have matched something in format list.\n",
361 else if (CFStringHasPrefix(type, registered_name_type_prefix))
363 int len = CFStringGetLength(type) - CFStringGetLength(registered_name_type_prefix);
364 name = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
365 CFStringGetCharacters(type, CFRangeMake(CFStringGetLength(registered_name_type_prefix), len),
371 int len = strlenW(mac_type_name_prefix) + CFStringGetLength(type);
372 name = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
373 memcpy(name, mac_type_name_prefix, sizeof(mac_type_name_prefix));
374 CFStringGetCharacters(type, CFRangeMake(0, CFStringGetLength(type)),
375 (UniChar*)name + strlenW(mac_type_name_prefix));
379 format = register_format(RegisterClipboardFormatW(name), type);
381 ERR("Failed to register format for type %s name %s\n", debugstr_cf(type), debugstr_w(name));
383 HeapFree(GetProcessHeap(), 0, name);
386 TRACE(" -> %p/%s\n", format, debugstr_format(format ? format->format_id : 0));
391 /**************************************************************************
394 * Convert string data between code pages or to/from wide characters. The
395 * special value of (UINT)-1 for a code page indicates to use wide
398 static HANDLE convert_text(const void *src, int src_len, UINT src_cp, UINT dest_cp)
406 if (src_cp == (UINT)-1)
409 wstr_len = src_len / sizeof(WCHAR);
415 wstr_len = MultiByteToWideChar(src_cp, 0, src, src_len, NULL, 0);
416 if (!src_len || ((const char*)src)[src_len - 1]) wstr_len += 1;
417 temp = HeapAlloc(GetProcessHeap(), 0, wstr_len * sizeof(WCHAR));
418 MultiByteToWideChar(src_cp, 0, src, src_len, temp, wstr_len);
419 temp[wstr_len - 1] = 0;
423 if (dest_cp == (UINT)-1)
425 handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, wstr_len * sizeof(WCHAR));
426 if (handle && (p = GlobalLock(handle)))
428 memcpy(p, wstr, wstr_len * sizeof(WCHAR));
429 GlobalUnlock(handle);
437 len = WideCharToMultiByte(dest_cp, 0, wstr, wstr_len, NULL, 0, NULL, NULL);
438 if (!wstr_len || wstr[wstr_len - 1]) len += 1;
439 handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, len);
441 if (handle && (p = GlobalLock(handle)))
443 WideCharToMultiByte(dest_cp, 0, wstr, wstr_len, p, len, NULL, NULL);
445 GlobalUnlock(handle);
454 /**************************************************************************
455 * convert_unicodetext_to_codepage
457 static HANDLE convert_unicodetext_to_codepage(HANDLE unicode_handle, UINT cp)
459 LPWSTR unicode_string = GlobalLock(unicode_handle);
464 ret = convert_text(unicode_string, GlobalSize(unicode_handle), -1, cp);
465 GlobalUnlock(unicode_handle);
472 /***********************************************************************
475 * Return the size of the bitmap info structure including color table.
477 static int bitmap_info_size(const BITMAPINFO *info, WORD coloruse)
479 unsigned int colors, size, masks = 0;
481 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
483 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER*)info;
484 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
485 return sizeof(BITMAPCOREHEADER) + colors *
486 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
488 else /* assume BITMAPINFOHEADER */
490 colors = info->bmiHeader.biClrUsed;
491 if (!colors && (info->bmiHeader.biBitCount <= 8))
492 colors = 1 << info->bmiHeader.biBitCount;
493 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
494 size = max(info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD));
495 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
500 /***********************************************************************
501 * create_dib_from_bitmap
503 * Allocates a packed DIB and copies the bitmap data into it.
505 static HGLOBAL create_dib_from_bitmap(HBITMAP hBmp)
511 LPBITMAPINFOHEADER pbmiHeader;
512 unsigned int cDataSize, cPackedSize, OffsetBits;
515 if (!GetObjectW(hBmp, sizeof(bmp), &bmp)) return 0;
518 * A packed DIB contains a BITMAPINFO structure followed immediately by
519 * an optional color palette and the pixel data.
522 /* Calculate the size of the packed DIB */
523 cDataSize = abs(bmp.bmHeight) * (((bmp.bmWidth * bmp.bmBitsPixel + 31) / 8) & ~3);
524 cPackedSize = sizeof(BITMAPINFOHEADER)
525 + ((bmp.bmBitsPixel <= 8) ? (sizeof(RGBQUAD) * (1 << bmp.bmBitsPixel)) : 0)
527 /* Get the offset to the bits */
528 OffsetBits = cPackedSize - cDataSize;
530 /* Allocate the packed DIB */
531 TRACE("\tAllocating packed DIB of size %d\n", cPackedSize);
532 hPackedDIB = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, cPackedSize);
535 WARN("Could not allocate packed DIB!\n");
539 /* A packed DIB starts with a BITMAPINFOHEADER */
540 pPackedDIB = GlobalLock(hPackedDIB);
541 pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
543 /* Init the BITMAPINFOHEADER */
544 pbmiHeader->biSize = sizeof(BITMAPINFOHEADER);
545 pbmiHeader->biWidth = bmp.bmWidth;
546 pbmiHeader->biHeight = bmp.bmHeight;
547 pbmiHeader->biPlanes = 1;
548 pbmiHeader->biBitCount = bmp.bmBitsPixel;
549 pbmiHeader->biCompression = BI_RGB;
550 pbmiHeader->biSizeImage = 0;
551 pbmiHeader->biXPelsPerMeter = pbmiHeader->biYPelsPerMeter = 0;
552 pbmiHeader->biClrUsed = 0;
553 pbmiHeader->biClrImportant = 0;
555 /* Retrieve the DIB bits from the bitmap and fill in the
556 * DIB color table if present */
558 nLinesCopied = GetDIBits(hdc, /* Handle to device context */
559 hBmp, /* Handle to bitmap */
560 0, /* First scan line to set in dest bitmap */
561 bmp.bmHeight, /* Number of scan lines to copy */
562 pPackedDIB + OffsetBits, /* [out] Address of array for bitmap bits */
563 (LPBITMAPINFO) pbmiHeader, /* [out] Address of BITMAPINFO structure */
564 0); /* RGB or palette index */
565 GlobalUnlock(hPackedDIB);
568 /* Cleanup if GetDIBits failed */
569 if (nLinesCopied != bmp.bmHeight)
571 TRACE("\tGetDIBits returned %d. Actual lines=%d\n", nLinesCopied, bmp.bmHeight);
572 GlobalFree(hPackedDIB);
579 /**************************************************************************
580 * import_clipboard_data
582 * Generic import clipboard data routine.
584 static HANDLE import_clipboard_data(CFDataRef data)
586 HANDLE data_handle = NULL;
588 size_t len = CFDataGetLength(data);
593 /* Turn on the DDESHARE flag to enable shared 32 bit memory */
594 data_handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, len);
598 if ((p = GlobalLock(data_handle)))
600 memcpy(p, CFDataGetBytePtr(data), len);
601 GlobalUnlock(data_handle);
605 GlobalFree(data_handle);
614 /**************************************************************************
615 * import_bmp_to_bitmap
617 * Import BMP data, converting to CF_BITMAP format.
619 static HANDLE import_bmp_to_bitmap(CFDataRef data)
622 HANDLE dib = import_bmp_to_dib(data);
625 if (dib && (bmi = GlobalLock(dib)))
632 offset = bitmap_info_size(bmi, DIB_RGB_COLORS);
634 ret = CreateDIBitmap(hdc, &bmi->bmiHeader, CBM_INIT, (LPBYTE)bmi + offset,
635 bmi, DIB_RGB_COLORS);
638 ReleaseDC(NULL, hdc);
646 /**************************************************************************
649 * Import BMP data, converting to CF_DIB format. This just entails
650 * stripping the BMP file format header.
652 static HANDLE import_bmp_to_dib(CFDataRef data)
655 BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)CFDataGetBytePtr(data);
656 CFIndex len = CFDataGetLength(data);
658 if (len >= sizeof(*bfh) + sizeof(BITMAPCOREHEADER) &&
659 bfh->bfType == 0x4d42 /* "BM" */)
661 BITMAPINFO *bmi = (BITMAPINFO*)(bfh + 1);
665 ret = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, len);
666 if (!ret || !(p = GlobalLock(ret)))
680 /**************************************************************************
681 * import_nsfilenames_to_hdrop
683 * Import NSFilenamesPboardType data, converting the property-list-
684 * serialized array of path strings to CF_HDROP.
686 static HANDLE import_nsfilenames_to_hdrop(CFDataRef data)
693 WCHAR **paths = NULL;
694 DROPFILES* dropfiles;
697 TRACE("data %s\n", debugstr_cf(data));
699 names = (CFArrayRef)CFPropertyListCreateWithData(NULL, data, kCFPropertyListImmutable,
701 if (!names || CFGetTypeID(names) != CFArrayGetTypeID())
703 WARN("failed to interpret data as a CFArray\n");
707 count = CFArrayGetCount(names);
710 for (i = 0; i < count; i++)
713 CFStringRef name = (CFStringRef)CFArrayGetValueAtIndex(names, i);
714 TRACE(" %s\n", debugstr_cf(name));
715 if (CFGetTypeID(name) != CFStringGetTypeID())
717 WARN("non-string in array\n");
721 this_len = CFStringGetMaximumSizeOfFileSystemRepresentation(name);
726 buffer = HeapAlloc(GetProcessHeap(), 0, len);
729 WARN("failed to allocate buffer for file-system representations\n");
733 paths = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, count * sizeof(paths[0]));
736 WARN("failed to allocate array of DOS paths\n");
740 for (i = 0; i < count; i++)
742 CFStringRef name = (CFStringRef)CFArrayGetValueAtIndex(names, i);
743 if (!CFStringGetFileSystemRepresentation(name, buffer, len))
745 WARN("failed to get file-system representation for %s\n", debugstr_cf(name));
748 paths[i] = wine_get_dos_file_name(buffer);
751 WARN("failed to get DOS path for %s\n", debugstr_a(buffer));
756 len = 1; /* for the terminating null */
757 for (i = 0; i < count; i++)
758 len += strlenW(paths[i]) + 1;
760 hdrop = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, sizeof(*dropfiles) + len * sizeof(WCHAR));
761 if (!hdrop || !(dropfiles = GlobalLock(hdrop)))
763 WARN("failed to allocate HDROP\n");
769 dropfiles->pFiles = sizeof(*dropfiles);
772 dropfiles->fNC = FALSE;
773 dropfiles->fWide = TRUE;
775 p = (WCHAR*)(dropfiles + 1);
776 for (i = 0; i < count; i++)
778 strcpyW(p, paths[i]);
788 for (i = 0; i < count; i++)
789 HeapFree(GetProcessHeap(), 0, paths[i]);
790 HeapFree(GetProcessHeap(), 0, paths);
792 HeapFree(GetProcessHeap(), 0, buffer);
793 if (names) CFRelease(names);
798 /**************************************************************************
799 * import_oemtext_to_text
801 * Import CF_OEMTEXT data, converting the string to CF_TEXT.
803 static HANDLE import_oemtext_to_text(CFDataRef data)
805 return convert_text(CFDataGetBytePtr(data), CFDataGetLength(data), CP_OEMCP, CP_ACP);
809 /**************************************************************************
810 * import_oemtext_to_unicodetext
812 * Import CF_OEMTEXT data, converting the string to CF_UNICODETEXT.
814 static HANDLE import_oemtext_to_unicodetext(CFDataRef data)
816 return convert_text(CFDataGetBytePtr(data), CFDataGetLength(data), CP_OEMCP, -1);
820 /**************************************************************************
821 * import_text_to_oemtext
823 * Import CF_TEXT data, converting the string to CF_OEMTEXT.
825 static HANDLE import_text_to_oemtext(CFDataRef data)
827 return convert_text(CFDataGetBytePtr(data), CFDataGetLength(data), CP_ACP, CP_OEMCP);
831 /**************************************************************************
832 * import_text_to_unicodetext
834 * Import CF_TEXT data, converting the string to CF_UNICODETEXT.
836 static HANDLE import_text_to_unicodetext(CFDataRef data)
838 return convert_text(CFDataGetBytePtr(data), CFDataGetLength(data), CP_ACP, -1);
842 /**************************************************************************
843 * import_unicodetext_to_oemtext
845 * Import a CF_UNICODETEXT string, converting the string to CF_OEMTEXT.
847 static HANDLE import_unicodetext_to_oemtext(CFDataRef data)
849 return convert_text(CFDataGetBytePtr(data), CFDataGetLength(data), -1, CP_OEMCP);
853 /**************************************************************************
854 * import_unicodetext_to_text
856 * Import a CF_UNICODETEXT string, converting the string to CF_TEXT.
858 static HANDLE import_unicodetext_to_text(CFDataRef data)
860 return convert_text(CFDataGetBytePtr(data), CFDataGetLength(data), -1, CP_ACP);
864 /**************************************************************************
865 * import_utf8_to_oemtext
867 * Import a UTF-8 string, converting the string to CF_OEMTEXT.
869 static HANDLE import_utf8_to_oemtext(CFDataRef data)
871 HANDLE unicode_handle = import_utf8_to_unicodetext(data);
872 HANDLE ret = convert_unicodetext_to_codepage(unicode_handle, CP_OEMCP);
874 GlobalFree(unicode_handle);
879 /**************************************************************************
880 * import_utf8_to_text
882 * Import a UTF-8 string, converting the string to CF_TEXT.
884 static HANDLE import_utf8_to_text(CFDataRef data)
886 HANDLE unicode_handle = import_utf8_to_unicodetext(data);
887 HANDLE ret = convert_unicodetext_to_codepage(unicode_handle, CP_ACP);
889 GlobalFree(unicode_handle);
894 /**************************************************************************
895 * import_utf8_to_unicodetext
897 * Import a UTF-8 string, converting the string to CF_UNICODETEXT.
899 static HANDLE import_utf8_to_unicodetext(CFDataRef data)
902 unsigned long data_len;
903 unsigned long new_lines = 0;
906 HANDLE unicode_handle = NULL;
908 src = CFDataGetBytePtr(data);
909 data_len = CFDataGetLength(data);
910 for (i = 0; i < data_len; i++)
916 if ((dst = HeapAlloc(GetProcessHeap(), 0, data_len + new_lines + 1)))
920 for (i = 0, j = 0; i < data_len; i++)
929 count = MultiByteToWideChar(CP_UTF8, 0, dst, -1, NULL, 0);
930 unicode_handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, count * sizeof(WCHAR));
934 WCHAR *textW = GlobalLock(unicode_handle);
935 MultiByteToWideChar(CP_UTF8, 0, dst, -1, textW, count);
936 GlobalUnlock(unicode_handle);
939 HeapFree(GetProcessHeap(), 0, dst);
942 return unicode_handle;
946 /**************************************************************************
947 * export_clipboard_data
949 * Generic export clipboard data routine.
951 static CFDataRef export_clipboard_data(HANDLE data)
957 len = GlobalSize(data);
958 src = GlobalLock(data);
959 if (!src) return NULL;
961 ret = CFDataCreate(NULL, src, len);
968 /**************************************************************************
969 * export_bitmap_to_bmp
971 * Export CF_BITMAP to BMP file format.
973 static CFDataRef export_bitmap_to_bmp(HANDLE data)
975 CFDataRef ret = NULL;
978 dib = create_dib_from_bitmap(data);
981 ret = export_dib_to_bmp(dib);
989 /**************************************************************************
990 * export_codepage_to_utf8
992 * Export string data in a specified codepage to UTF-8.
994 static CFDataRef export_codepage_to_utf8(HANDLE data, UINT cp)
996 CFDataRef ret = NULL;
999 if ((str = GlobalLock(data)))
1001 HANDLE unicode = convert_text(str, GlobalSize(data), cp, -1);
1003 ret = export_unicodetext_to_utf8(unicode);
1005 GlobalFree(unicode);
1013 /**************************************************************************
1016 * Export CF_DIB to BMP file format. This just entails prepending a BMP
1017 * file format header to the data.
1019 static CFDataRef export_dib_to_bmp(HANDLE data)
1021 CFMutableDataRef ret = NULL;
1024 BITMAPFILEHEADER bfh;
1026 dibdata = GlobalLock(data);
1030 len = sizeof(bfh) + GlobalSize(data);
1031 ret = CFDataCreateMutable(NULL, len);
1034 bfh.bfType = 0x4d42; /* "BM" */
1036 bfh.bfReserved1 = 0;
1037 bfh.bfReserved2 = 0;
1038 bfh.bfOffBits = sizeof(bfh) + bitmap_info_size((BITMAPINFO*)dibdata, DIB_RGB_COLORS);
1039 CFDataAppendBytes(ret, (UInt8*)&bfh, sizeof(bfh));
1041 /* rest of bitmap is the same as the packed dib */
1042 CFDataAppendBytes(ret, (UInt8*)dibdata, len - sizeof(bfh));
1051 /**************************************************************************
1052 * export_hdrop_to_filenames
1054 * Export CF_HDROP to NSFilenamesPboardType data, which is a CFArray of
1055 * CFStrings (holding Unix paths) which is serialized as a property list.
1057 static CFDataRef export_hdrop_to_filenames(HANDLE data)
1059 CFDataRef ret = NULL;
1060 DROPFILES *dropfiles;
1061 CFMutableArrayRef filenames = NULL;
1063 WCHAR *buffer = NULL;
1064 size_t buffer_len = 0;
1066 TRACE("data %p\n", data);
1068 if (!(dropfiles = GlobalLock(data)))
1070 WARN("failed to lock data %p\n", data);
1074 filenames = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1077 WARN("failed to create filenames array\n");
1081 p = (char*)dropfiles + dropfiles->pFiles;
1082 while (dropfiles->fWide ? *(WCHAR*)p : *(char*)p)
1085 CFStringRef filename;
1087 TRACE(" %s\n", dropfiles->fWide ? debugstr_w(p) : debugstr_a(p));
1089 if (dropfiles->fWide)
1090 unixname = wine_get_unix_file_name(p);
1093 int len = MultiByteToWideChar(CP_ACP, 0, p, -1, NULL, 0);
1096 if (len > buffer_len)
1098 HeapFree(GetProcessHeap(), 0, buffer);
1099 buffer_len = len * 2;
1100 buffer = HeapAlloc(GetProcessHeap(), 0, buffer_len * sizeof(*buffer));
1103 MultiByteToWideChar(CP_ACP, 0, p, -1, buffer, buffer_len);
1104 unixname = wine_get_unix_file_name(buffer);
1111 WARN("failed to convert DOS path to Unix: %s\n",
1112 dropfiles->fWide ? debugstr_w(p) : debugstr_a(p));
1116 if (dropfiles->fWide)
1117 p = (WCHAR*)p + strlenW(p) + 1;
1119 p = (char*)p + strlen(p) + 1;
1121 filename = CFStringCreateWithFileSystemRepresentation(NULL, unixname);
1122 HeapFree(GetProcessHeap(), 0, unixname);
1125 WARN("failed to create CFString from Unix path %s\n", debugstr_a(unixname));
1129 CFArrayAppendValue(filenames, filename);
1130 CFRelease(filename);
1133 ret = CFPropertyListCreateData(NULL, filenames, kCFPropertyListXMLFormat_v1_0, 0, NULL);
1136 HeapFree(GetProcessHeap(), 0, buffer);
1138 if (filenames) CFRelease(filenames);
1139 TRACE(" -> %s\n", debugstr_cf(ret));
1144 /**************************************************************************
1145 * export_oemtext_to_utf8
1147 * Export CF_OEMTEXT to UTF-8.
1149 static CFDataRef export_oemtext_to_utf8(HANDLE data)
1151 return export_codepage_to_utf8(data, CP_OEMCP);
1155 /**************************************************************************
1156 * export_text_to_utf8
1158 * Export CF_TEXT to UTF-8.
1160 static CFDataRef export_text_to_utf8(HANDLE data)
1162 return export_codepage_to_utf8(data, CP_ACP);
1166 /**************************************************************************
1167 * export_unicodetext_to_utf8
1169 * Export CF_UNICODETEXT to UTF-8.
1171 static CFDataRef export_unicodetext_to_utf8(HANDLE data)
1173 CFMutableDataRef ret;
1177 src = GlobalLock(data);
1178 if (!src) return NULL;
1180 dst_len = WideCharToMultiByte(CP_UTF8, 0, src, -1, NULL, 0, NULL, NULL);
1181 if (dst_len) dst_len--; /* Leave off null terminator. */
1182 ret = CFDataCreateMutable(NULL, dst_len);
1188 CFDataSetLength(ret, dst_len);
1189 dst = (LPSTR)CFDataGetMutableBytePtr(ret);
1190 WideCharToMultiByte(CP_UTF8, 0, src, -1, dst, dst_len, NULL, NULL);
1192 /* Remove carriage returns */
1193 for (i = 0, j = 0; i < dst_len; i++)
1195 if (dst[i] == '\r' &&
1196 (i + 1 >= dst_len || dst[i + 1] == '\n' || dst[i + 1] == '\0'))
1200 CFDataSetLength(ret, j);
1208 /**************************************************************************
1209 * get_clipboard_info
1211 static BOOL get_clipboard_info(LPCLIPBOARDINFO cbinfo)
1215 SERVER_START_REQ(set_clipboard_info)
1219 if (wine_server_call_err(req))
1221 ERR("Failed to get clipboard owner.\n");
1225 cbinfo->hwnd_owner = wine_server_ptr_handle(reply->old_owner);
1226 cbinfo->flags = reply->flags;
1237 /**************************************************************************
1240 static BOOL release_ownership(void)
1244 SERVER_START_REQ(set_clipboard_info)
1246 req->flags = SET_CB_RELOWNER | SET_CB_SEQNO;
1248 if (wine_server_call_err(req))
1249 ERR("Failed to set clipboard.\n");
1259 /**************************************************************************
1260 * check_clipboard_ownership
1262 static void check_clipboard_ownership(HWND *owner)
1264 CLIPBOARDINFO cbinfo;
1266 if (owner) *owner = NULL;
1268 /* If Wine thinks we're the clipboard owner but Mac OS X thinks we're not
1269 the pasteboard owner, update Wine. */
1270 if (get_clipboard_info(&cbinfo) && (cbinfo.flags & CB_PROCESS))
1272 if (!(cbinfo.flags & CB_OPEN) && !macdrv_is_pasteboard_owner())
1274 TRACE("Lost clipboard ownership\n");
1276 if (OpenClipboard(cbinfo.hwnd_owner))
1278 /* Destroy private objects */
1279 SendMessageW(cbinfo.hwnd_owner, WM_DESTROYCLIPBOARD, 0, 0);
1281 /* Give up ownership of the windows clipboard */
1282 release_ownership();
1287 *owner = cbinfo.hwnd_owner;
1292 /**************************************************************************
1293 * Mac User Driver Clipboard Exports
1294 **************************************************************************/
1297 /**************************************************************************
1298 * AcquireClipboard (MACDRV.@)
1300 int CDECL macdrv_AcquireClipboard(HWND hwnd)
1302 TRACE("hwnd %p\n", hwnd);
1303 check_clipboard_ownership(NULL);
1308 /**************************************************************************
1309 * CountClipboardFormats (MACDRV.@)
1311 INT CDECL macdrv_CountClipboardFormats(void)
1313 CFMutableSetRef seen_formats;
1320 check_clipboard_ownership(NULL);
1322 seen_formats = CFSetCreateMutable(NULL, 0, NULL);
1325 WARN("Failed to allocate set to track seen formats\n");
1329 types = macdrv_copy_pasteboard_types();
1332 WARN("Failed to copy pasteboard types\n");
1333 CFRelease(seen_formats);
1337 count = CFArrayGetCount(types);
1338 TRACE("got %ld types\n", count);
1340 for (i = 0; i < count; i++)
1342 CFStringRef type = CFArrayGetValueAtIndex(types, i);
1343 WINE_CLIPFORMAT* format;
1346 while ((format = format_for_type(format, type)))
1348 TRACE("for type %s got format %p/%s\n", debugstr_cf(type), format, debugstr_format(format->format_id));
1350 if (!CFSetContainsValue(seen_formats, (void*)format->format_id))
1353 CFSetAddValue(seen_formats, (void*)format->format_id);
1358 CFRelease(seen_formats);
1359 TRACE(" -> %d\n", ret);
1364 /**************************************************************************
1365 * EmptyClipboard (MACDRV.@)
1367 * Empty cached clipboard data.
1369 void CDECL macdrv_EmptyClipboard(BOOL keepunowned)
1371 TRACE("keepunowned %d\n", keepunowned);
1372 macdrv_clear_pasteboard();
1376 /**************************************************************************
1377 * EndClipboardUpdate (MACDRV.@)
1379 void CDECL macdrv_EndClipboardUpdate(void)
1382 check_clipboard_ownership(NULL);
1386 /**************************************************************************
1387 * EnumClipboardFormats (MACDRV.@)
1389 UINT CDECL macdrv_EnumClipboardFormats(UINT prev_format)
1396 TRACE("prev_format %s\n", debugstr_format(prev_format));
1397 check_clipboard_ownership(NULL);
1399 types = macdrv_copy_pasteboard_types();
1402 WARN("Failed to copy pasteboard types\n");
1406 count = CFArrayGetCount(types);
1407 TRACE("got %ld types\n", count);
1417 CFMutableArrayRef formats = CFArrayCreateMutable(NULL, 0, NULL);
1420 WARN("Failed to allocate array to track formats\n");
1425 for (i = 0; i < count; i++)
1427 CFStringRef type = CFArrayGetValueAtIndex(types, i);
1428 WINE_CLIPFORMAT* format;
1431 while ((format = format_for_type(format, type)))
1433 TRACE("for type %s got format %p/%s\n", debugstr_cf(type), format, debugstr_format(format->format_id));
1435 if (format->synthesized)
1437 /* Don't override a real value with a synthesized value. */
1438 if (!CFArrayContainsValue(formats, CFRangeMake(0, CFArrayGetCount(formats)), (void*)format->format_id))
1439 CFArrayAppendValue(formats, (void*)format->format_id);
1443 /* If the type was already in the array, it must have been synthesized
1444 because this one's real. Remove the synthesized entry in favor of
1446 CFIndex index = CFArrayGetFirstIndexOfValue(formats, CFRangeMake(0, CFArrayGetCount(formats)),
1447 (void*)format->format_id);
1448 if (index != kCFNotFound)
1449 CFArrayRemoveValueAtIndex(formats, index);
1450 CFArrayAppendValue(formats, (void*)format->format_id);
1455 count = CFArrayGetCount(formats);
1456 i = CFArrayGetFirstIndexOfValue(formats, CFRangeMake(0, count), (void*)prev_format);
1457 if (i == kCFNotFound || i + 1 >= count)
1460 ret = (UINT)CFArrayGetValueAtIndex(formats, i + 1);
1466 CFStringRef type = CFArrayGetValueAtIndex(types, 0);
1467 WINE_CLIPFORMAT *format = format_for_type(NULL, type);
1469 ret = format ? format->format_id : 0;
1473 TRACE(" -> %u\n", ret);
1478 /**************************************************************************
1479 * GetClipboardData (MACDRV.@)
1481 HANDLE CDECL macdrv_GetClipboardData(UINT desired_format)
1486 CFStringRef type, best_type;
1487 WINE_CLIPFORMAT* best_format = NULL;
1490 TRACE("desired_format %s\n", debugstr_format(desired_format));
1491 check_clipboard_ownership(NULL);
1493 types = macdrv_copy_pasteboard_types();
1496 WARN("Failed to copy pasteboard types\n");
1500 count = CFArrayGetCount(types);
1501 TRACE("got %ld types\n", count);
1503 for (i = 0; (!best_format || best_format->synthesized) && i < count; i++)
1505 WINE_CLIPFORMAT* format;
1507 type = CFArrayGetValueAtIndex(types, i);
1510 while ((!best_format || best_format->synthesized) && (format = format_for_type(format, type)))
1512 TRACE("for type %s got format %p/%s\n", debugstr_cf(type), format, debugstr_format(format ? format->format_id : 0));
1514 if (format->format_id == desired_format)
1516 /* The best format is the matching one which is not synthesized. Failing that,
1517 the best format is the first matching synthesized format. */
1518 if (!format->synthesized || !best_format)
1521 best_format = format;
1529 CFDataRef pasteboard_data = macdrv_copy_pasteboard_data(best_type);
1531 TRACE("got pasteboard data for type %s: %s\n", debugstr_cf(best_type), debugstr_cf(pasteboard_data));
1533 if (pasteboard_data)
1535 data = best_format->import_func(pasteboard_data);
1536 CFRelease(pasteboard_data);
1541 TRACE(" -> %p\n", data);
1546 /**************************************************************************
1547 * IsClipboardFormatAvailable (MACDRV.@)
1549 BOOL CDECL macdrv_IsClipboardFormatAvailable(UINT desired_format)
1556 TRACE("desired_format %s\n", debugstr_format(desired_format));
1557 check_clipboard_ownership(NULL);
1559 types = macdrv_copy_pasteboard_types();
1562 WARN("Failed to copy pasteboard types\n");
1566 count = CFArrayGetCount(types);
1567 TRACE("got %d types\n", count);
1569 for (i = 0; !found && i < count; i++)
1571 CFStringRef type = CFArrayGetValueAtIndex(types, i);
1572 WINE_CLIPFORMAT* format;
1575 while (!found && (format = format_for_type(format, type)))
1577 TRACE("for type %s got format %s\n", debugstr_cf(type), debugstr_format(format->format_id));
1579 if (format->format_id == desired_format)
1585 TRACE(" -> %d\n", found);
1590 /**************************************************************************
1591 * SetClipboardData (MACDRV.@)
1593 BOOL CDECL macdrv_SetClipboardData(UINT format_id, HANDLE data, BOOL owner)
1596 macdrv_window window;
1597 WINE_CLIPFORMAT *format;
1598 CFDataRef cfdata = NULL;
1600 check_clipboard_ownership(&hwnd_owner);
1601 window = macdrv_get_cocoa_window(GetAncestor(hwnd_owner, GA_ROOT), FALSE);
1602 TRACE("format_id %s data %p owner %d hwnd_owner %p window %p)\n", debugstr_format(format_id), data, owner, hwnd_owner, window);
1604 /* Find the "natural" format for this format_id (the one which isn't
1605 synthesized from another type). */
1606 LIST_FOR_EACH_ENTRY(format, &format_list, WINE_CLIPFORMAT, entry)
1607 if (format->format_id == format_id && !format->synthesized) break;
1609 if (&format->entry == &format_list && !(format = insert_clipboard_format(format_id, NULL)))
1611 WARN("Failed to register clipboard format %s\n", debugstr_format(format_id));
1615 /* Export the data to the Mac pasteboard. */
1618 if (!format->export_func || !(cfdata = format->export_func(data)))
1620 WARN("Failed to export %s data to type %s\n", debugstr_format(format_id), debugstr_cf(format->type));
1625 if (macdrv_set_pasteboard_data(format->type, cfdata, window))
1626 TRACE("Set pasteboard data for type %s: %s\n", debugstr_cf(format->type), debugstr_cf(cfdata));
1629 WARN("Failed to set pasteboard data for type %s: %s\n", debugstr_cf(format->type), debugstr_cf(cfdata));
1630 if (cfdata) CFRelease(cfdata);
1634 if (cfdata) CFRelease(cfdata);
1636 /* Find any other formats for this format_id (the exportable synthesized ones). */
1637 LIST_FOR_EACH_ENTRY(format, &format_list, WINE_CLIPFORMAT, entry)
1639 if (format->format_id == format_id && format->synthesized && format->export_func)
1641 /* We have a synthesized format for this format ID. Add its type to the pasteboard. */
1642 TRACE("Synthesized from format %s: type %s\n", debugstr_format(format_id), debugstr_cf(format->type));
1646 cfdata = format->export_func(data);
1649 WARN("Failed to export %s data to type %s\n", debugstr_format(format->format_id), debugstr_cf(format->type));
1656 if (macdrv_set_pasteboard_data(format->type, cfdata, window))
1657 TRACE(" ... set pasteboard data: %s\n", debugstr_cf(cfdata));
1659 WARN(" ... failed to set pasteboard data: %s\n", debugstr_cf(cfdata));
1661 if (cfdata) CFRelease(cfdata);
1667 /* FIXME: According to MSDN, the caller is entitled to lock and read from
1668 data until CloseClipboard is called. So, we should defer this cleanup. */
1669 if ((format_id >= CF_GDIOBJFIRST && format_id <= CF_GDIOBJLAST) ||
1670 format_id == CF_BITMAP ||
1671 format_id == CF_DIB ||
1672 format_id == CF_PALETTE)
1676 else if (format_id == CF_METAFILEPICT)
1678 DeleteMetaFile(((METAFILEPICT *)GlobalLock(data))->hMF);
1681 else if (format_id == CF_ENHMETAFILE)
1683 DeleteEnhMetaFile(data);
1685 else if (format_id < CF_PRIVATEFIRST || CF_PRIVATELAST < format_id)
1695 /**************************************************************************
1696 * MACDRV Private Clipboard Exports
1697 **************************************************************************/
1700 /**************************************************************************
1701 * macdrv_clipboard_process_attach
1703 void macdrv_clipboard_process_attach(void)
1707 /* Register built-in formats */
1708 for (i = 0; i < sizeof(builtin_format_ids)/sizeof(builtin_format_ids[0]); i++)
1710 WINE_CLIPFORMAT *format;
1712 if (!(format = HeapAlloc(GetProcessHeap(), 0, sizeof(*format)))) break;
1713 format->format_id = builtin_format_ids[i].id;
1714 format->type = CFRetain(builtin_format_ids[i].type);
1715 format->import_func = builtin_format_ids[i].import;
1716 format->export_func = builtin_format_ids[i].export;
1717 format->synthesized = builtin_format_ids[i].synthesized;
1718 list_add_tail(&format_list, &format->entry);
1721 /* Register known mappings between Windows formats and Mac types */
1722 for (i = 0; i < sizeof(builtin_format_names)/sizeof(builtin_format_names[0]); i++)
1723 insert_clipboard_format(RegisterClipboardFormatW(builtin_format_names[i].name),
1724 builtin_format_names[i].type);
1728 /**************************************************************************
1729 * query_pasteboard_data
1731 BOOL query_pasteboard_data(HWND hwnd, CFStringRef type)
1734 CLIPBOARDINFO cbinfo;
1735 WINE_CLIPFORMAT* format;
1736 CFArrayRef types = NULL;
1739 TRACE("hwnd %p type %s\n", hwnd, debugstr_cf(type));
1741 if (get_clipboard_info(&cbinfo))
1742 hwnd = cbinfo.hwnd_owner;
1745 while ((format = format_for_type(format, type)))
1747 WINE_CLIPFORMAT* base_format;
1749 TRACE("for type %s got format %p/%s\n", debugstr_cf(type), format, debugstr_format(format->format_id));
1751 if (!format->synthesized)
1753 TRACE("Sending WM_RENDERFORMAT message for format %s to hwnd %p\n", debugstr_format(format->format_id), hwnd);
1754 SendMessageW(hwnd, WM_RENDERFORMAT, format->format_id, 0);
1761 types = macdrv_copy_pasteboard_types();
1764 WARN("Failed to copy pasteboard types\n");
1768 range = CFRangeMake(0, CFArrayGetCount(types));
1771 /* The type maps to a synthesized format. Now look up what type that format maps to natively
1772 (not synthesized). For example, if type is "public.utf8-plain-text", then this format may
1773 have an ID of CF_TEXT. From CF_TEXT, we want to find "org.winehq.builtin.text" to see if
1774 that type is present in the pasteboard. If it is, then the app must have promised it and
1775 we can ask it to render it. (If it had put it on the clipboard immediately, then the
1776 pasteboard would also have data for "public.utf8-plain-text" and we wouldn't be here.) If
1777 "org.winehq.builtin.text" is not on the pasteboard, then one of the other text formats is
1778 presumably responsible for the promise that we're trying to satisfy, so we keep looking. */
1779 LIST_FOR_EACH_ENTRY(base_format, &format_list, WINE_CLIPFORMAT, entry)
1781 if (base_format->format_id == format->format_id && !base_format->synthesized &&
1782 CFArrayContainsValue(types, range, base_format->type))
1784 TRACE("Sending WM_RENDERFORMAT message for format %s to hwnd %p\n", debugstr_format(base_format->format_id), hwnd);
1785 SendMessageW(hwnd, WM_RENDERFORMAT, base_format->format_id, 0);
1793 if (types) CFRelease(types);