d3d8/tests: Add a system memory miptree layout test.
[wine.git] / dlls / winemac.drv / clipboard.c
blob188d4e2a78dbb8cf55d4773a7c505007fa4d37b7
1 /*
2 * Mac clipboard driver
4 * Copyright 1994 Martin Ayotte
5 * 1996 Alex Korobka
6 * 1999 Noel Borthwick
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
25 #include "config.h"
27 #include "macdrv.h"
28 #include "winuser.h"
29 #include "shellapi.h"
30 #include "shlobj.h"
31 #include "wine/list.h"
32 #include "wine/server.h"
33 #include "wine/unicode.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(clipboard);
39 /**************************************************************************
40 * Types
41 **************************************************************************/
43 typedef struct
45 HWND hwnd_owner;
46 UINT flags;
47 } CLIPBOARDINFO, *LPCLIPBOARDINFO;
49 typedef HANDLE (*DRVIMPORTFUNC)(CFDataRef data);
50 typedef CFDataRef (*DRVEXPORTFUNC)(HANDLE data);
52 typedef struct _WINE_CLIPFORMAT
54 struct list entry;
55 UINT format_id;
56 CFStringRef type;
57 DRVIMPORTFUNC import_func;
58 DRVEXPORTFUNC export_func;
59 BOOL synthesized;
60 struct _WINE_CLIPFORMAT *natural_format;
61 } WINE_CLIPFORMAT;
64 /**************************************************************************
65 * Constants
66 **************************************************************************/
69 /**************************************************************************
70 * Forward Function Declarations
71 **************************************************************************/
73 static HANDLE import_clipboard_data(CFDataRef data);
74 static HANDLE import_bmp_to_bitmap(CFDataRef data);
75 static HANDLE import_bmp_to_dib(CFDataRef data);
76 static HANDLE import_dib_to_bitmap(CFDataRef data);
77 static HANDLE import_enhmetafile(CFDataRef data);
78 static HANDLE import_enhmetafile_to_metafilepict(CFDataRef data);
79 static HANDLE import_metafilepict(CFDataRef data);
80 static HANDLE import_metafilepict_to_enhmetafile(CFDataRef data);
81 static HANDLE import_nsfilenames_to_hdrop(CFDataRef data);
82 static HANDLE import_oemtext_to_text(CFDataRef data);
83 static HANDLE import_oemtext_to_unicodetext(CFDataRef data);
84 static HANDLE import_text_to_oemtext(CFDataRef data);
85 static HANDLE import_text_to_unicodetext(CFDataRef data);
86 static HANDLE import_unicodetext_to_oemtext(CFDataRef data);
87 static HANDLE import_unicodetext_to_text(CFDataRef data);
88 static HANDLE import_utf8_to_oemtext(CFDataRef data);
89 static HANDLE import_utf8_to_text(CFDataRef data);
90 static HANDLE import_utf8_to_unicodetext(CFDataRef data);
91 static HANDLE import_utf16_to_oemtext(CFDataRef data);
92 static HANDLE import_utf16_to_text(CFDataRef data);
93 static HANDLE import_utf16_to_unicodetext(CFDataRef data);
95 static CFDataRef export_clipboard_data(HANDLE data);
96 static CFDataRef export_bitmap_to_bmp(HANDLE data);
97 static CFDataRef export_bitmap_to_dib(HANDLE data);
98 static CFDataRef export_dib_to_bmp(HANDLE data);
99 static CFDataRef export_enhmetafile(HANDLE data);
100 static CFDataRef export_hdrop_to_filenames(HANDLE data);
101 static CFDataRef export_metafilepict(HANDLE data);
102 static CFDataRef export_oemtext_to_utf8(HANDLE data);
103 static CFDataRef export_oemtext_to_utf16(HANDLE data);
104 static CFDataRef export_text_to_utf8(HANDLE data);
105 static CFDataRef export_text_to_utf16(HANDLE data);
106 static CFDataRef export_unicodetext_to_utf8(HANDLE data);
107 static CFDataRef export_unicodetext_to_utf16(HANDLE data);
110 /**************************************************************************
111 * Static Variables
112 **************************************************************************/
114 /* Clipboard formats */
115 static struct list format_list = LIST_INIT(format_list);
117 /* There are two naming schemes involved and we want to have a mapping between
118 them. There are Win32 clipboard format names and there are Mac pasteboard
119 types.
121 The Win32 standard clipboard formats don't have names, but they are associated
122 with Mac pasteboard types through the following tables, which are used to
123 initialize the format_list. Where possible, the standard clipboard formats
124 are mapped to predefined pasteboard type UTIs. Otherwise, we create Wine-
125 specific types of the form "org.winehq.builtin.<format>", where <format> is
126 the name of the symbolic constant for the format minus "CF_" and lowercased.
127 E.g. CF_BITMAP -> org.winehq.builtin.bitmap.
129 Win32 clipboard formats which originate in a Windows program may be registered
130 with an arbitrary name. We construct a Mac pasteboard type from these by
131 prepending "org.winehq.registered." to the registered name.
133 Likewise, Mac pasteboard types which originate in other apps may have
134 arbitrary type strings. We ignore these.
136 Summary:
137 Win32 clipboard format names:
138 <none> standard clipboard format; maps via
139 format_list to either a predefined Mac UTI
140 or org.winehq.builtin.<format>.
141 <other> name registered within Win32 land; maps to
142 org.winehq.registered.<other>
143 Mac pasteboard type names:
144 org.winehq.builtin.<format ID> representation of Win32 standard clipboard
145 format for which there was no corresponding
146 predefined Mac UTI; maps via format_list
147 org.winehq.registered.<format name> representation of Win32 registered
148 clipboard format name; maps to <format name>
149 <other> Mac pasteboard type originating with system
150 or other apps; either maps via format_list
151 to a standard clipboard format or ignored
154 static const struct
156 UINT id;
157 CFStringRef type;
158 DRVIMPORTFUNC import;
159 DRVEXPORTFUNC export;
160 BOOL synthesized;
161 } builtin_format_ids[] =
163 { CF_DIF, CFSTR("org.winehq.builtin.dif"), import_clipboard_data, export_clipboard_data, FALSE },
164 { CF_DSPBITMAP, CFSTR("org.winehq.builtin.dspbitmap"), import_clipboard_data, export_clipboard_data, FALSE },
165 { CF_DSPENHMETAFILE, CFSTR("org.winehq.builtin.dspenhmetafile"), import_clipboard_data, export_clipboard_data, FALSE },
166 { CF_DSPMETAFILEPICT, CFSTR("org.winehq.builtin.dspmetafilepict"), import_clipboard_data, export_clipboard_data, FALSE },
167 { CF_DSPTEXT, CFSTR("org.winehq.builtin.dsptext"), import_clipboard_data, export_clipboard_data, FALSE },
168 { CF_LOCALE, CFSTR("org.winehq.builtin.locale"), import_clipboard_data, export_clipboard_data, FALSE },
169 { CF_OWNERDISPLAY, CFSTR("org.winehq.builtin.ownerdisplay"), import_clipboard_data, export_clipboard_data, FALSE },
170 { CF_PALETTE, CFSTR("org.winehq.builtin.palette"), import_clipboard_data, export_clipboard_data, FALSE },
171 { CF_PENDATA, CFSTR("org.winehq.builtin.pendata"), import_clipboard_data, export_clipboard_data, FALSE },
172 { CF_RIFF, CFSTR("org.winehq.builtin.riff"), import_clipboard_data, export_clipboard_data, FALSE },
173 { CF_SYLK, CFSTR("org.winehq.builtin.sylk"), import_clipboard_data, export_clipboard_data, FALSE },
174 { CF_TIFF, CFSTR("public.tiff"), import_clipboard_data, export_clipboard_data, FALSE },
175 { CF_WAVE, CFSTR("com.microsoft.waveform-audio"), import_clipboard_data, export_clipboard_data, FALSE },
177 { CF_UNICODETEXT, CFSTR("org.winehq.builtin.unicodetext"), import_clipboard_data, export_clipboard_data, FALSE },
178 { CF_TEXT, CFSTR("org.winehq.builtin.unicodetext"), import_unicodetext_to_text, NULL, TRUE },
179 { CF_OEMTEXT, CFSTR("org.winehq.builtin.unicodetext"), import_unicodetext_to_oemtext, NULL, TRUE },
181 { CF_TEXT, CFSTR("org.winehq.builtin.text"), import_clipboard_data, export_clipboard_data, FALSE },
182 { CF_OEMTEXT, CFSTR("org.winehq.builtin.text"), import_text_to_oemtext, NULL, TRUE },
183 { CF_UNICODETEXT, CFSTR("org.winehq.builtin.text"), import_text_to_unicodetext, NULL, TRUE },
185 { CF_OEMTEXT, CFSTR("org.winehq.builtin.oemtext"), import_clipboard_data, export_clipboard_data, FALSE },
186 { CF_TEXT, CFSTR("org.winehq.builtin.oemtext"), import_oemtext_to_text, NULL, TRUE },
187 { CF_UNICODETEXT, CFSTR("org.winehq.builtin.oemtext"), import_oemtext_to_unicodetext, NULL, TRUE },
189 { CF_TEXT, CFSTR("public.utf8-plain-text"), import_utf8_to_text, export_text_to_utf8, TRUE },
190 { CF_OEMTEXT, CFSTR("public.utf8-plain-text"), import_utf8_to_oemtext, export_oemtext_to_utf8, TRUE },
191 { CF_UNICODETEXT, CFSTR("public.utf8-plain-text"), import_utf8_to_unicodetext, export_unicodetext_to_utf8, TRUE },
193 { CF_TEXT, CFSTR("public.utf16-plain-text"), import_utf16_to_text, export_text_to_utf16, TRUE },
194 { CF_OEMTEXT, CFSTR("public.utf16-plain-text"), import_utf16_to_oemtext, export_oemtext_to_utf16, TRUE },
195 { CF_UNICODETEXT, CFSTR("public.utf16-plain-text"), import_utf16_to_unicodetext, export_unicodetext_to_utf16,TRUE },
197 { CF_BITMAP, CFSTR("org.winehq.builtin.bitmap"), import_bmp_to_bitmap, export_bitmap_to_bmp, FALSE },
198 { CF_DIB, CFSTR("org.winehq.builtin.bitmap"), import_bmp_to_dib, export_dib_to_bmp, TRUE },
199 { CF_DIBV5, CFSTR("org.winehq.builtin.bitmap"), import_bmp_to_dib, export_dib_to_bmp, TRUE },
201 { CF_DIB, CFSTR("org.winehq.builtin.dib"), import_clipboard_data, export_clipboard_data, FALSE },
202 { CF_BITMAP, CFSTR("org.winehq.builtin.dib"), import_dib_to_bitmap, export_bitmap_to_dib, TRUE },
203 { CF_DIBV5, CFSTR("org.winehq.builtin.dib"), import_clipboard_data, export_clipboard_data, TRUE },
205 { CF_DIBV5, CFSTR("org.winehq.builtin.dibv5"), import_clipboard_data, export_clipboard_data, FALSE },
206 { CF_BITMAP, CFSTR("org.winehq.builtin.dibv5"), import_dib_to_bitmap, export_bitmap_to_dib, TRUE },
207 { CF_DIB, CFSTR("org.winehq.builtin.dibv5"), import_clipboard_data, export_clipboard_data, TRUE },
209 { CF_BITMAP, CFSTR("com.microsoft.bmp"), import_bmp_to_bitmap, export_bitmap_to_bmp, TRUE },
210 { CF_DIB, CFSTR("com.microsoft.bmp"), import_bmp_to_dib, export_dib_to_bmp, TRUE },
211 { CF_DIBV5, CFSTR("com.microsoft.bmp"), import_bmp_to_dib, export_dib_to_bmp, TRUE },
213 { CF_HDROP, CFSTR("org.winehq.builtin.hdrop"), import_clipboard_data, export_clipboard_data, FALSE },
214 { CF_HDROP, CFSTR("NSFilenamesPboardType"), import_nsfilenames_to_hdrop, export_hdrop_to_filenames, TRUE },
216 { CF_ENHMETAFILE, CFSTR("org.winehq.builtin.enhmetafile"), import_enhmetafile, export_enhmetafile, FALSE },
217 { CF_METAFILEPICT, CFSTR("org.winehq.builtin.enhmetafile"), import_enhmetafile_to_metafilepict, NULL, TRUE },
219 { CF_METAFILEPICT, CFSTR("org.winehq.builtin.metafilepict"), import_metafilepict, export_metafilepict, FALSE },
220 { CF_ENHMETAFILE, CFSTR("org.winehq.builtin.metafilepict"), import_metafilepict_to_enhmetafile, NULL, TRUE },
223 static const WCHAR wszRichTextFormat[] = {'R','i','c','h',' ','T','e','x','t',' ','F','o','r','m','a','t',0};
224 static const WCHAR wszGIF[] = {'G','I','F',0};
225 static const WCHAR wszJFIF[] = {'J','F','I','F',0};
226 static const WCHAR wszPNG[] = {'P','N','G',0};
227 static const WCHAR wszHTMLFormat[] = {'H','T','M','L',' ','F','o','r','m','a','t',0};
228 static const struct
230 LPCWSTR name;
231 CFStringRef type;
232 DRVIMPORTFUNC import;
233 DRVEXPORTFUNC export;
234 } builtin_format_names[] =
236 { wszRichTextFormat, CFSTR("public.rtf"), import_clipboard_data, export_clipboard_data },
237 { wszGIF, CFSTR("com.compuserve.gif"), import_clipboard_data, export_clipboard_data },
238 { wszJFIF, CFSTR("public.jpeg"), import_clipboard_data, export_clipboard_data },
239 { wszPNG, CFSTR("public.png"), import_clipboard_data, export_clipboard_data },
240 { wszHTMLFormat, CFSTR("public.html"), import_clipboard_data, export_clipboard_data },
241 { CFSTR_SHELLURLW, CFSTR("public.url"), import_utf8_to_text, export_text_to_utf8 },
244 /* The prefix prepended to a Win32 clipboard format name to make a Mac pasteboard type. */
245 static const CFStringRef registered_name_type_prefix = CFSTR("org.winehq.registered.");
248 /**************************************************************************
249 * Internal Clipboard implementation methods
250 **************************************************************************/
253 * format_list functions
256 /**************************************************************************
257 * debugstr_format
259 const char *debugstr_format(UINT id)
261 WCHAR buffer[256];
263 if (GetClipboardFormatNameW(id, buffer, 256))
264 return wine_dbg_sprintf("0x%04x %s", id, debugstr_w(buffer));
266 switch (id)
268 #define BUILTIN(id) case id: return #id;
269 BUILTIN(CF_TEXT)
270 BUILTIN(CF_BITMAP)
271 BUILTIN(CF_METAFILEPICT)
272 BUILTIN(CF_SYLK)
273 BUILTIN(CF_DIF)
274 BUILTIN(CF_TIFF)
275 BUILTIN(CF_OEMTEXT)
276 BUILTIN(CF_DIB)
277 BUILTIN(CF_PALETTE)
278 BUILTIN(CF_PENDATA)
279 BUILTIN(CF_RIFF)
280 BUILTIN(CF_WAVE)
281 BUILTIN(CF_UNICODETEXT)
282 BUILTIN(CF_ENHMETAFILE)
283 BUILTIN(CF_HDROP)
284 BUILTIN(CF_LOCALE)
285 BUILTIN(CF_DIBV5)
286 BUILTIN(CF_OWNERDISPLAY)
287 BUILTIN(CF_DSPTEXT)
288 BUILTIN(CF_DSPBITMAP)
289 BUILTIN(CF_DSPMETAFILEPICT)
290 BUILTIN(CF_DSPENHMETAFILE)
291 #undef BUILTIN
292 default: return wine_dbg_sprintf("0x%04x", id);
297 /**************************************************************************
298 * insert_clipboard_format
300 static WINE_CLIPFORMAT *insert_clipboard_format(UINT id, CFStringRef type)
302 WINE_CLIPFORMAT *format;
304 format = HeapAlloc(GetProcessHeap(), 0, sizeof(*format));
306 if (format == NULL)
308 WARN("No more memory for a new format!\n");
309 return NULL;
311 format->format_id = id;
312 format->import_func = import_clipboard_data;
313 format->export_func = export_clipboard_data;
314 format->synthesized = FALSE;
315 format->natural_format = NULL;
317 if (type)
318 format->type = CFStringCreateCopy(NULL, type);
319 else
321 WCHAR buffer[256];
323 if (!GetClipboardFormatNameW(format->format_id, buffer, sizeof(buffer) / sizeof(buffer[0])))
325 WARN("failed to get name for format %s; error 0x%08x\n", debugstr_format(format->format_id), GetLastError());
326 HeapFree(GetProcessHeap(), 0, format);
327 return NULL;
330 format->type = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%S"),
331 registered_name_type_prefix, buffer);
334 list_add_tail(&format_list, &format->entry);
336 TRACE("Registering format %s type %s\n", debugstr_format(format->format_id),
337 debugstr_cf(format->type));
339 return format;
343 /**************************************************************************
344 * register_format
346 * Register a custom Mac clipboard format.
348 static WINE_CLIPFORMAT* register_format(UINT id, CFStringRef type)
350 WINE_CLIPFORMAT *format;
352 /* walk format chain to see if it's already registered */
353 LIST_FOR_EACH_ENTRY(format, &format_list, WINE_CLIPFORMAT, entry)
354 if (format->format_id == id) return format;
356 return insert_clipboard_format(id, type);
360 /**************************************************************************
361 * format_for_type
363 static WINE_CLIPFORMAT* format_for_type(WINE_CLIPFORMAT *current, CFStringRef type)
365 struct list *ptr = current ? &current->entry : &format_list;
366 WINE_CLIPFORMAT *format = NULL;
368 TRACE("current %p/%s type %s\n", current, debugstr_format(current ? current->format_id : 0), debugstr_cf(type));
370 while ((ptr = list_next(&format_list, ptr)))
372 format = LIST_ENTRY(ptr, WINE_CLIPFORMAT, entry);
373 if (CFEqual(format->type, type))
374 goto done;
377 format = NULL;
378 if (!current)
380 if (CFStringHasPrefix(type, CFSTR("org.winehq.builtin.")))
382 ERR("Shouldn't happen. Built-in type %s should have matched something in format list.\n",
383 debugstr_cf(type));
385 else if (CFStringHasPrefix(type, registered_name_type_prefix))
387 LPWSTR name;
388 int len = CFStringGetLength(type) - CFStringGetLength(registered_name_type_prefix);
390 name = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
391 CFStringGetCharacters(type, CFRangeMake(CFStringGetLength(registered_name_type_prefix), len),
392 (UniChar*)name);
393 name[len] = 0;
395 format = register_format(RegisterClipboardFormatW(name), type);
396 if (!format)
397 ERR("Failed to register format for type %s name %s\n", debugstr_cf(type), debugstr_w(name));
399 HeapFree(GetProcessHeap(), 0, name);
403 done:
404 TRACE(" -> %p/%s\n", format, debugstr_format(format ? format->format_id : 0));
405 return format;
409 /**************************************************************************
410 * natural_format_for_format
412 * Find the "natural" format for this format_id (the one which isn't
413 * synthesized from another type).
415 static WINE_CLIPFORMAT* natural_format_for_format(UINT format_id)
417 WINE_CLIPFORMAT *format;
419 LIST_FOR_EACH_ENTRY(format, &format_list, WINE_CLIPFORMAT, entry)
420 if (format->format_id == format_id && !format->synthesized) break;
422 if (&format->entry == &format_list)
423 format = NULL;
425 TRACE("%s -> %p/%s\n", debugstr_format(format_id), format, debugstr_cf(format ? format->type : NULL));
426 return format;
430 /**************************************************************************
431 * convert_text
433 * Convert string data between code pages or to/from wide characters. The
434 * special value of (UINT)-1 for a code page indicates to use wide
435 * characters.
437 static HANDLE convert_text(const void *src, int src_len, UINT src_cp, UINT dest_cp)
439 HANDLE ret = NULL;
440 const WCHAR *wstr;
441 int wstr_len;
442 HANDLE handle;
443 char *p;
445 if (src_cp == (UINT)-1)
447 wstr = src;
448 wstr_len = src_len / sizeof(WCHAR);
450 else
452 WCHAR *temp;
454 wstr_len = MultiByteToWideChar(src_cp, 0, src, src_len, NULL, 0);
455 if (!src_len || ((const char*)src)[src_len - 1]) wstr_len += 1;
456 temp = HeapAlloc(GetProcessHeap(), 0, wstr_len * sizeof(WCHAR));
457 MultiByteToWideChar(src_cp, 0, src, src_len, temp, wstr_len);
458 temp[wstr_len - 1] = 0;
459 wstr = temp;
462 if (dest_cp == (UINT)-1)
464 handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, wstr_len * sizeof(WCHAR));
465 if (handle && (p = GlobalLock(handle)))
467 memcpy(p, wstr, wstr_len * sizeof(WCHAR));
468 GlobalUnlock(handle);
469 ret = handle;
472 else
474 INT len;
476 len = WideCharToMultiByte(dest_cp, 0, wstr, wstr_len, NULL, 0, NULL, NULL);
477 if (!wstr_len || wstr[wstr_len - 1]) len += 1;
478 handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, len);
480 if (handle && (p = GlobalLock(handle)))
482 WideCharToMultiByte(dest_cp, 0, wstr, wstr_len, p, len, NULL, NULL);
483 p[len - 1] = 0;
484 GlobalUnlock(handle);
485 ret = handle;
489 return ret;
493 /**************************************************************************
494 * convert_unicodetext_to_codepage
496 static HANDLE convert_unicodetext_to_codepage(HANDLE unicode_handle, UINT cp)
498 LPWSTR unicode_string = GlobalLock(unicode_handle);
499 HANDLE ret = NULL;
501 if (unicode_string)
503 ret = convert_text(unicode_string, GlobalSize(unicode_handle), -1, cp);
504 GlobalUnlock(unicode_handle);
507 return ret;
511 /***********************************************************************
512 * bitmap_info_size
514 * Return the size of the bitmap info structure including color table.
516 static int bitmap_info_size(const BITMAPINFO *info, WORD coloruse)
518 unsigned int colors, size, masks = 0;
520 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
522 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER*)info;
523 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
524 return sizeof(BITMAPCOREHEADER) + colors *
525 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
527 else /* assume BITMAPINFOHEADER */
529 colors = info->bmiHeader.biClrUsed;
530 if (!colors && (info->bmiHeader.biBitCount <= 8))
531 colors = 1 << info->bmiHeader.biBitCount;
532 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
533 size = max(info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD));
534 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
539 /***********************************************************************
540 * create_dib_from_bitmap
542 * Allocates a packed DIB and copies the bitmap data into it.
544 static HGLOBAL create_dib_from_bitmap(HBITMAP hBmp)
546 BITMAP bmp;
547 HDC hdc;
548 HGLOBAL hPackedDIB;
549 LPBYTE pPackedDIB;
550 LPBITMAPINFOHEADER pbmiHeader;
551 unsigned int cDataSize, cPackedSize, OffsetBits;
552 int nLinesCopied;
554 if (!GetObjectW(hBmp, sizeof(bmp), &bmp)) return 0;
557 * A packed DIB contains a BITMAPINFO structure followed immediately by
558 * an optional color palette and the pixel data.
561 /* Calculate the size of the packed DIB */
562 cDataSize = abs(bmp.bmHeight) * (((bmp.bmWidth * bmp.bmBitsPixel + 31) / 8) & ~3);
563 cPackedSize = sizeof(BITMAPINFOHEADER)
564 + ((bmp.bmBitsPixel <= 8) ? (sizeof(RGBQUAD) * (1 << bmp.bmBitsPixel)) : 0)
565 + cDataSize;
566 /* Get the offset to the bits */
567 OffsetBits = cPackedSize - cDataSize;
569 /* Allocate the packed DIB */
570 TRACE("\tAllocating packed DIB of size %d\n", cPackedSize);
571 hPackedDIB = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, cPackedSize);
572 if (!hPackedDIB)
574 WARN("Could not allocate packed DIB!\n");
575 return 0;
578 /* A packed DIB starts with a BITMAPINFOHEADER */
579 pPackedDIB = GlobalLock(hPackedDIB);
580 pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
582 /* Init the BITMAPINFOHEADER */
583 pbmiHeader->biSize = sizeof(BITMAPINFOHEADER);
584 pbmiHeader->biWidth = bmp.bmWidth;
585 pbmiHeader->biHeight = bmp.bmHeight;
586 pbmiHeader->biPlanes = 1;
587 pbmiHeader->biBitCount = bmp.bmBitsPixel;
588 pbmiHeader->biCompression = BI_RGB;
589 pbmiHeader->biSizeImage = 0;
590 pbmiHeader->biXPelsPerMeter = pbmiHeader->biYPelsPerMeter = 0;
591 pbmiHeader->biClrUsed = 0;
592 pbmiHeader->biClrImportant = 0;
594 /* Retrieve the DIB bits from the bitmap and fill in the
595 * DIB color table if present */
596 hdc = GetDC(0);
597 nLinesCopied = GetDIBits(hdc, /* Handle to device context */
598 hBmp, /* Handle to bitmap */
599 0, /* First scan line to set in dest bitmap */
600 bmp.bmHeight, /* Number of scan lines to copy */
601 pPackedDIB + OffsetBits, /* [out] Address of array for bitmap bits */
602 (LPBITMAPINFO) pbmiHeader, /* [out] Address of BITMAPINFO structure */
603 0); /* RGB or palette index */
604 GlobalUnlock(hPackedDIB);
605 ReleaseDC(0, hdc);
607 /* Cleanup if GetDIBits failed */
608 if (nLinesCopied != bmp.bmHeight)
610 TRACE("\tGetDIBits returned %d. Actual lines=%d\n", nLinesCopied, bmp.bmHeight);
611 GlobalFree(hPackedDIB);
612 hPackedDIB = 0;
614 return hPackedDIB;
618 /**************************************************************************
619 * import_clipboard_data
621 * Generic import clipboard data routine.
623 static HANDLE import_clipboard_data(CFDataRef data)
625 HANDLE data_handle = NULL;
627 size_t len = CFDataGetLength(data);
628 if (len)
630 LPVOID p;
632 /* Turn on the DDESHARE flag to enable shared 32 bit memory */
633 data_handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, len);
634 if (!data_handle)
635 return NULL;
637 if ((p = GlobalLock(data_handle)))
639 memcpy(p, CFDataGetBytePtr(data), len);
640 GlobalUnlock(data_handle);
642 else
644 GlobalFree(data_handle);
645 data_handle = NULL;
649 return data_handle;
653 /**************************************************************************
654 * create_bitmap_from_dib
656 * Given a packed DIB, creates a bitmap object from it.
658 static HANDLE create_bitmap_from_dib(HANDLE dib)
660 HANDLE ret = 0;
661 BITMAPINFO *bmi;
663 if (dib && (bmi = GlobalLock(dib)))
665 HDC hdc;
666 unsigned int offset;
668 hdc = GetDC(NULL);
670 offset = bitmap_info_size(bmi, DIB_RGB_COLORS);
672 ret = CreateDIBitmap(hdc, &bmi->bmiHeader, CBM_INIT, (LPBYTE)bmi + offset,
673 bmi, DIB_RGB_COLORS);
675 GlobalUnlock(dib);
676 ReleaseDC(NULL, hdc);
679 return ret;
683 /**************************************************************************
684 * import_bmp_to_bitmap
686 * Import BMP data, converting to CF_BITMAP format.
688 static HANDLE import_bmp_to_bitmap(CFDataRef data)
690 HANDLE ret;
691 HANDLE dib = import_bmp_to_dib(data);
693 ret = create_bitmap_from_dib(dib);
695 GlobalFree(dib);
696 return ret;
700 /**************************************************************************
701 * import_bmp_to_dib
703 * Import BMP data, converting to CF_DIB or CF_DIBV5 format. This just
704 * entails stripping the BMP file format header.
706 static HANDLE import_bmp_to_dib(CFDataRef data)
708 HANDLE ret = 0;
709 BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)CFDataGetBytePtr(data);
710 CFIndex len = CFDataGetLength(data);
712 if (len >= sizeof(*bfh) + sizeof(BITMAPCOREHEADER) &&
713 bfh->bfType == 0x4d42 /* "BM" */)
715 BITMAPINFO *bmi = (BITMAPINFO*)(bfh + 1);
716 BYTE* p;
718 len -= sizeof(*bfh);
719 ret = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, len);
720 if (!ret || !(p = GlobalLock(ret)))
722 GlobalFree(ret);
723 return 0;
726 memcpy(p, bmi, len);
727 GlobalUnlock(ret);
730 return ret;
734 /**************************************************************************
735 * import_dib_to_bitmap
737 * Import device-independent bitmap data, converting to CF_BITMAP format.
739 static HANDLE import_dib_to_bitmap(CFDataRef data)
741 HANDLE ret;
742 HANDLE dib = import_clipboard_data(data);
744 ret = create_bitmap_from_dib(dib);
746 GlobalFree(dib);
748 return ret;
752 /**************************************************************************
753 * import_enhmetafile
755 * Import enhanced metafile data, converting it to CF_ENHMETAFILE.
757 static HANDLE import_enhmetafile(CFDataRef data)
759 HANDLE ret = 0;
760 CFIndex len = CFDataGetLength(data);
762 TRACE("data %s\n", debugstr_cf(data));
764 if (len)
765 ret = SetEnhMetaFileBits(len, (const BYTE*)CFDataGetBytePtr(data));
767 return ret;
771 /**************************************************************************
772 * import_enhmetafile_to_metafilepict
774 * Import enhanced metafile data, converting it to CF_METAFILEPICT.
776 static HANDLE import_enhmetafile_to_metafilepict(CFDataRef data)
778 HANDLE ret = 0, hmf;
779 HANDLE hemf;
780 METAFILEPICT *mfp;
782 if ((hmf = GlobalAlloc(0, sizeof(*mfp))) && (hemf = import_enhmetafile(data)))
784 ENHMETAHEADER header;
785 HDC hdc = CreateCompatibleDC(0);
786 unsigned int size = GetWinMetaFileBits(hemf, 0, NULL, MM_ISOTROPIC, hdc);
787 BYTE *bytes;
789 bytes = HeapAlloc(GetProcessHeap(), 0, size);
790 if (bytes && GetEnhMetaFileHeader(hemf, sizeof(header), &header) &&
791 GetWinMetaFileBits(hemf, size, bytes, MM_ISOTROPIC, hdc))
793 mfp = GlobalLock(hmf);
794 mfp->mm = MM_ISOTROPIC;
795 mfp->xExt = header.rclFrame.right - header.rclFrame.left;
796 mfp->yExt = header.rclFrame.bottom - header.rclFrame.top;
797 mfp->hMF = SetMetaFileBitsEx(size, bytes);
798 GlobalUnlock(hmf);
800 ret = hmf;
803 if (hdc) DeleteDC(hdc);
804 HeapFree(GetProcessHeap(), 0, bytes);
805 DeleteEnhMetaFile(hemf);
808 if (!ret) GlobalFree(hmf);
809 return ret;
813 /**************************************************************************
814 * import_metafilepict
816 * Import metafile picture data, converting it to CF_METAFILEPICT.
818 static HANDLE import_metafilepict(CFDataRef data)
820 HANDLE ret = 0;
821 CFIndex len = CFDataGetLength(data);
822 METAFILEPICT *mfp;
824 TRACE("data %s\n", debugstr_cf(data));
826 if (len >= sizeof(*mfp) && (ret = GlobalAlloc(0, sizeof(*mfp))))
828 const BYTE *bytes = (const BYTE*)CFDataGetBytePtr(data);
830 mfp = GlobalLock(ret);
831 memcpy(mfp, bytes, sizeof(*mfp));
832 mfp->hMF = SetMetaFileBitsEx(len - sizeof(*mfp), bytes + sizeof(*mfp));
833 GlobalUnlock(ret);
836 return ret;
840 /**************************************************************************
841 * import_metafilepict_to_enhmetafile
843 * Import metafile picture data, converting it to CF_ENHMETAFILE.
845 static HANDLE import_metafilepict_to_enhmetafile(CFDataRef data)
847 HANDLE ret = 0;
848 CFIndex len = CFDataGetLength(data);
849 const METAFILEPICT *mfp;
851 TRACE("data %s\n", debugstr_cf(data));
853 if (len >= sizeof(*mfp))
855 mfp = (const METAFILEPICT*)CFDataGetBytePtr(data);
856 ret = SetWinMetaFileBits(len - sizeof(*mfp), (const BYTE*)(mfp + 1), NULL, mfp);
859 return ret;
863 /**************************************************************************
864 * import_nsfilenames_to_hdrop
866 * Import NSFilenamesPboardType data, converting the property-list-
867 * serialized array of path strings to CF_HDROP.
869 static HANDLE import_nsfilenames_to_hdrop(CFDataRef data)
871 HDROP hdrop = NULL;
872 CFArrayRef names;
873 CFIndex count, i;
874 size_t len;
875 char *buffer = NULL;
876 WCHAR **paths = NULL;
877 DROPFILES* dropfiles;
878 UniChar* p;
880 TRACE("data %s\n", debugstr_cf(data));
882 names = (CFArrayRef)CFPropertyListCreateWithData(NULL, data, kCFPropertyListImmutable,
883 NULL, NULL);
884 if (!names || CFGetTypeID(names) != CFArrayGetTypeID())
886 WARN("failed to interpret data as a CFArray\n");
887 goto done;
890 count = CFArrayGetCount(names);
892 len = 0;
893 for (i = 0; i < count; i++)
895 CFIndex this_len;
896 CFStringRef name = (CFStringRef)CFArrayGetValueAtIndex(names, i);
897 TRACE(" %s\n", debugstr_cf(name));
898 if (CFGetTypeID(name) != CFStringGetTypeID())
900 WARN("non-string in array\n");
901 goto done;
904 this_len = CFStringGetMaximumSizeOfFileSystemRepresentation(name);
905 if (this_len > len)
906 len = this_len;
909 buffer = HeapAlloc(GetProcessHeap(), 0, len);
910 if (!buffer)
912 WARN("failed to allocate buffer for file-system representations\n");
913 goto done;
916 paths = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, count * sizeof(paths[0]));
917 if (!paths)
919 WARN("failed to allocate array of DOS paths\n");
920 goto done;
923 for (i = 0; i < count; i++)
925 CFStringRef name = (CFStringRef)CFArrayGetValueAtIndex(names, i);
926 if (!CFStringGetFileSystemRepresentation(name, buffer, len))
928 WARN("failed to get file-system representation for %s\n", debugstr_cf(name));
929 goto done;
931 paths[i] = wine_get_dos_file_name(buffer);
932 if (!paths[i])
934 WARN("failed to get DOS path for %s\n", debugstr_a(buffer));
935 goto done;
939 len = 1; /* for the terminating null */
940 for (i = 0; i < count; i++)
941 len += strlenW(paths[i]) + 1;
943 hdrop = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, sizeof(*dropfiles) + len * sizeof(WCHAR));
944 if (!hdrop || !(dropfiles = GlobalLock(hdrop)))
946 WARN("failed to allocate HDROP\n");
947 GlobalFree(hdrop);
948 hdrop = NULL;
949 goto done;
952 dropfiles->pFiles = sizeof(*dropfiles);
953 dropfiles->pt.x = 0;
954 dropfiles->pt.y = 0;
955 dropfiles->fNC = FALSE;
956 dropfiles->fWide = TRUE;
958 p = (WCHAR*)(dropfiles + 1);
959 for (i = 0; i < count; i++)
961 strcpyW(p, paths[i]);
962 p += strlenW(p) + 1;
964 *p = 0;
966 GlobalUnlock(hdrop);
968 done:
969 if (paths)
971 for (i = 0; i < count; i++)
972 HeapFree(GetProcessHeap(), 0, paths[i]);
973 HeapFree(GetProcessHeap(), 0, paths);
975 HeapFree(GetProcessHeap(), 0, buffer);
976 if (names) CFRelease(names);
977 return hdrop;
981 /**************************************************************************
982 * import_oemtext_to_text
984 * Import CF_OEMTEXT data, converting the string to CF_TEXT.
986 static HANDLE import_oemtext_to_text(CFDataRef data)
988 return convert_text(CFDataGetBytePtr(data), CFDataGetLength(data), CP_OEMCP, CP_ACP);
992 /**************************************************************************
993 * import_oemtext_to_unicodetext
995 * Import CF_OEMTEXT data, converting the string to CF_UNICODETEXT.
997 static HANDLE import_oemtext_to_unicodetext(CFDataRef data)
999 return convert_text(CFDataGetBytePtr(data), CFDataGetLength(data), CP_OEMCP, -1);
1003 /**************************************************************************
1004 * import_text_to_oemtext
1006 * Import CF_TEXT data, converting the string to CF_OEMTEXT.
1008 static HANDLE import_text_to_oemtext(CFDataRef data)
1010 return convert_text(CFDataGetBytePtr(data), CFDataGetLength(data), CP_ACP, CP_OEMCP);
1014 /**************************************************************************
1015 * import_text_to_unicodetext
1017 * Import CF_TEXT data, converting the string to CF_UNICODETEXT.
1019 static HANDLE import_text_to_unicodetext(CFDataRef data)
1021 return convert_text(CFDataGetBytePtr(data), CFDataGetLength(data), CP_ACP, -1);
1025 /**************************************************************************
1026 * import_unicodetext_to_oemtext
1028 * Import a CF_UNICODETEXT string, converting the string to CF_OEMTEXT.
1030 static HANDLE import_unicodetext_to_oemtext(CFDataRef data)
1032 return convert_text(CFDataGetBytePtr(data), CFDataGetLength(data), -1, CP_OEMCP);
1036 /**************************************************************************
1037 * import_unicodetext_to_text
1039 * Import a CF_UNICODETEXT string, converting the string to CF_TEXT.
1041 static HANDLE import_unicodetext_to_text(CFDataRef data)
1043 return convert_text(CFDataGetBytePtr(data), CFDataGetLength(data), -1, CP_ACP);
1047 /**************************************************************************
1048 * import_utf8_to_oemtext
1050 * Import a UTF-8 string, converting the string to CF_OEMTEXT.
1052 static HANDLE import_utf8_to_oemtext(CFDataRef data)
1054 HANDLE unicode_handle = import_utf8_to_unicodetext(data);
1055 HANDLE ret = convert_unicodetext_to_codepage(unicode_handle, CP_OEMCP);
1057 GlobalFree(unicode_handle);
1058 return ret;
1062 /**************************************************************************
1063 * import_utf8_to_text
1065 * Import a UTF-8 string, converting the string to CF_TEXT.
1067 static HANDLE import_utf8_to_text(CFDataRef data)
1069 HANDLE unicode_handle = import_utf8_to_unicodetext(data);
1070 HANDLE ret = convert_unicodetext_to_codepage(unicode_handle, CP_ACP);
1072 GlobalFree(unicode_handle);
1073 return ret;
1077 /**************************************************************************
1078 * import_utf8_to_unicodetext
1080 * Import a UTF-8 string, converting the string to CF_UNICODETEXT.
1082 static HANDLE import_utf8_to_unicodetext(CFDataRef data)
1084 const BYTE *src;
1085 unsigned long src_len;
1086 unsigned long new_lines = 0;
1087 LPSTR dst;
1088 unsigned long i, j;
1089 HANDLE unicode_handle = NULL;
1091 src = CFDataGetBytePtr(data);
1092 src_len = CFDataGetLength(data);
1093 for (i = 0; i < src_len; i++)
1095 if (src[i] == '\n')
1096 new_lines++;
1099 if ((dst = HeapAlloc(GetProcessHeap(), 0, src_len + new_lines + 1)))
1101 UINT count;
1103 for (i = 0, j = 0; i < src_len; i++)
1105 if (src[i] == '\n')
1106 dst[j++] = '\r';
1108 dst[j++] = src[i];
1110 dst[j] = 0;
1112 count = MultiByteToWideChar(CP_UTF8, 0, dst, -1, NULL, 0);
1113 unicode_handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, count * sizeof(WCHAR));
1115 if (unicode_handle)
1117 WCHAR *textW = GlobalLock(unicode_handle);
1118 MultiByteToWideChar(CP_UTF8, 0, dst, -1, textW, count);
1119 GlobalUnlock(unicode_handle);
1122 HeapFree(GetProcessHeap(), 0, dst);
1125 return unicode_handle;
1129 /**************************************************************************
1130 * import_utf16_to_oemtext
1132 * Import a UTF-16 string, converting the string to CF_OEMTEXT.
1134 static HANDLE import_utf16_to_oemtext(CFDataRef data)
1136 HANDLE unicode_handle = import_utf16_to_unicodetext(data);
1137 HANDLE ret = convert_unicodetext_to_codepage(unicode_handle, CP_OEMCP);
1139 GlobalFree(unicode_handle);
1140 return ret;
1144 /**************************************************************************
1145 * import_utf16_to_text
1147 * Import a UTF-16 string, converting the string to CF_TEXT.
1149 static HANDLE import_utf16_to_text(CFDataRef data)
1151 HANDLE unicode_handle = import_utf16_to_unicodetext(data);
1152 HANDLE ret = convert_unicodetext_to_codepage(unicode_handle, CP_ACP);
1154 GlobalFree(unicode_handle);
1155 return ret;
1159 /**************************************************************************
1160 * import_utf16_to_unicodetext
1162 * Import a UTF-8 string, converting the string to CF_UNICODETEXT.
1164 static HANDLE import_utf16_to_unicodetext(CFDataRef data)
1166 const WCHAR *src;
1167 unsigned long src_len;
1168 unsigned long new_lines = 0;
1169 LPWSTR dst;
1170 unsigned long i, j;
1171 HANDLE unicode_handle;
1173 src = (const WCHAR *)CFDataGetBytePtr(data);
1174 src_len = CFDataGetLength(data) / sizeof(WCHAR);
1175 for (i = 0; i < src_len; i++)
1177 if (src[i] == '\n')
1178 new_lines++;
1181 if ((unicode_handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, (src_len + new_lines + 1) * sizeof(WCHAR))))
1183 dst = GlobalLock(unicode_handle);
1185 for (i = 0, j = 0; i < src_len; i++)
1187 if (src[i] == '\n')
1188 dst[j++] = '\r';
1190 dst[j++] = src[i];
1192 dst[j] = 0;
1194 GlobalUnlock(unicode_handle);
1197 return unicode_handle;
1201 /**************************************************************************
1202 * export_clipboard_data
1204 * Generic export clipboard data routine.
1206 static CFDataRef export_clipboard_data(HANDLE data)
1208 CFDataRef ret;
1209 UINT len;
1210 LPVOID src;
1212 len = GlobalSize(data);
1213 src = GlobalLock(data);
1214 if (!src) return NULL;
1216 ret = CFDataCreate(NULL, src, len);
1217 GlobalUnlock(data);
1219 return ret;
1223 /**************************************************************************
1224 * export_bitmap_to_bmp
1226 * Export CF_BITMAP to BMP file format.
1228 static CFDataRef export_bitmap_to_bmp(HANDLE data)
1230 CFDataRef ret = NULL;
1231 HGLOBAL dib;
1233 dib = create_dib_from_bitmap(data);
1234 if (dib)
1236 ret = export_dib_to_bmp(dib);
1237 GlobalFree(dib);
1240 return ret;
1244 /**************************************************************************
1245 * export_bitmap_to_dib
1247 * Export CF_BITMAP to a raw packed device-independent bitmap.
1249 static CFDataRef export_bitmap_to_dib(HANDLE data)
1251 CFDataRef ret = NULL;
1252 HGLOBAL dib;
1254 dib = create_dib_from_bitmap(data);
1255 if (dib)
1257 ret = export_clipboard_data(dib);
1258 GlobalFree(dib);
1261 return ret;
1265 /**************************************************************************
1266 * export_codepage_to_utf8
1268 * Export string data in a specified codepage to UTF-8.
1270 static CFDataRef export_codepage_to_utf8(HANDLE data, UINT cp)
1272 CFDataRef ret = NULL;
1273 const char* str;
1275 if ((str = GlobalLock(data)))
1277 HANDLE unicode = convert_text(str, GlobalSize(data), cp, -1);
1279 ret = export_unicodetext_to_utf8(unicode);
1281 GlobalFree(unicode);
1282 GlobalUnlock(data);
1285 return ret;
1289 /**************************************************************************
1290 * export_codepage_to_utf16
1292 * Export string data in a specified codepage to UTF-16.
1294 static CFDataRef export_codepage_to_utf16(HANDLE data, UINT cp)
1296 CFDataRef ret = NULL;
1297 const char* str;
1299 if ((str = GlobalLock(data)))
1301 HANDLE unicode = convert_text(str, GlobalSize(data), cp, -1);
1303 ret = export_unicodetext_to_utf16(unicode);
1305 GlobalFree(unicode);
1306 GlobalUnlock(data);
1309 return ret;
1313 /**************************************************************************
1314 * export_dib_to_bmp
1316 * Export CF_DIB or CF_DIBV5 to BMP file format. This just entails
1317 * prepending a BMP file format header to the data.
1319 static CFDataRef export_dib_to_bmp(HANDLE data)
1321 CFMutableDataRef ret = NULL;
1322 BYTE *dibdata;
1323 CFIndex len;
1324 BITMAPFILEHEADER bfh;
1326 dibdata = GlobalLock(data);
1327 if (!dibdata)
1328 return NULL;
1330 len = sizeof(bfh) + GlobalSize(data);
1331 ret = CFDataCreateMutable(NULL, len);
1332 if (ret)
1334 bfh.bfType = 0x4d42; /* "BM" */
1335 bfh.bfSize = len;
1336 bfh.bfReserved1 = 0;
1337 bfh.bfReserved2 = 0;
1338 bfh.bfOffBits = sizeof(bfh) + bitmap_info_size((BITMAPINFO*)dibdata, DIB_RGB_COLORS);
1339 CFDataAppendBytes(ret, (UInt8*)&bfh, sizeof(bfh));
1341 /* rest of bitmap is the same as the packed dib */
1342 CFDataAppendBytes(ret, (UInt8*)dibdata, len - sizeof(bfh));
1345 GlobalUnlock(data);
1347 return ret;
1351 /**************************************************************************
1352 * export_enhmetafile
1354 * Export an enhanced metafile to data.
1356 static CFDataRef export_enhmetafile(HANDLE data)
1358 CFMutableDataRef ret = NULL;
1359 unsigned int size = GetEnhMetaFileBits(data, 0, NULL);
1361 TRACE("data %p\n", data);
1363 ret = CFDataCreateMutable(NULL, size);
1364 if (ret)
1366 CFDataSetLength(ret, size);
1367 GetEnhMetaFileBits(data, size, (BYTE*)CFDataGetMutableBytePtr(ret));
1370 TRACE(" -> %s\n", debugstr_cf(ret));
1371 return ret;
1375 /**************************************************************************
1376 * export_hdrop_to_filenames
1378 * Export CF_HDROP to NSFilenamesPboardType data, which is a CFArray of
1379 * CFStrings (holding Unix paths) which is serialized as a property list.
1381 static CFDataRef export_hdrop_to_filenames(HANDLE data)
1383 CFDataRef ret = NULL;
1384 DROPFILES *dropfiles;
1385 CFMutableArrayRef filenames = NULL;
1386 void *p;
1387 WCHAR *buffer = NULL;
1388 size_t buffer_len = 0;
1390 TRACE("data %p\n", data);
1392 if (!(dropfiles = GlobalLock(data)))
1394 WARN("failed to lock data %p\n", data);
1395 goto done;
1398 filenames = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1399 if (!filenames)
1401 WARN("failed to create filenames array\n");
1402 goto done;
1405 p = (char*)dropfiles + dropfiles->pFiles;
1406 while (dropfiles->fWide ? *(WCHAR*)p : *(char*)p)
1408 char *unixname;
1409 CFStringRef filename;
1411 TRACE(" %s\n", dropfiles->fWide ? debugstr_w(p) : debugstr_a(p));
1413 if (dropfiles->fWide)
1414 unixname = wine_get_unix_file_name(p);
1415 else
1417 int len = MultiByteToWideChar(CP_ACP, 0, p, -1, NULL, 0);
1418 if (len)
1420 if (len > buffer_len)
1422 HeapFree(GetProcessHeap(), 0, buffer);
1423 buffer_len = len * 2;
1424 buffer = HeapAlloc(GetProcessHeap(), 0, buffer_len * sizeof(*buffer));
1427 MultiByteToWideChar(CP_ACP, 0, p, -1, buffer, buffer_len);
1428 unixname = wine_get_unix_file_name(buffer);
1430 else
1431 unixname = NULL;
1433 if (!unixname)
1435 WARN("failed to convert DOS path to Unix: %s\n",
1436 dropfiles->fWide ? debugstr_w(p) : debugstr_a(p));
1437 goto done;
1440 if (dropfiles->fWide)
1441 p = (WCHAR*)p + strlenW(p) + 1;
1442 else
1443 p = (char*)p + strlen(p) + 1;
1445 filename = CFStringCreateWithFileSystemRepresentation(NULL, unixname);
1446 HeapFree(GetProcessHeap(), 0, unixname);
1447 if (!filename)
1449 WARN("failed to create CFString from Unix path %s\n", debugstr_a(unixname));
1450 goto done;
1453 CFArrayAppendValue(filenames, filename);
1454 CFRelease(filename);
1457 ret = CFPropertyListCreateData(NULL, filenames, kCFPropertyListXMLFormat_v1_0, 0, NULL);
1459 done:
1460 HeapFree(GetProcessHeap(), 0, buffer);
1461 GlobalUnlock(data);
1462 if (filenames) CFRelease(filenames);
1463 TRACE(" -> %s\n", debugstr_cf(ret));
1464 return ret;
1468 /**************************************************************************
1469 * export_metafilepict
1471 * Export a metafile to data.
1473 static CFDataRef export_metafilepict(HANDLE data)
1475 CFMutableDataRef ret = NULL;
1476 METAFILEPICT *mfp = GlobalLock(data);
1477 unsigned int size = GetMetaFileBitsEx(mfp->hMF, 0, NULL);
1479 TRACE("data %p\n", data);
1481 ret = CFDataCreateMutable(NULL, sizeof(*mfp) + size);
1482 if (ret)
1484 CFDataAppendBytes(ret, (UInt8*)mfp, sizeof(*mfp));
1485 CFDataIncreaseLength(ret, size);
1486 GetMetaFileBitsEx(mfp->hMF, size, (BYTE*)CFDataGetMutableBytePtr(ret) + sizeof(*mfp));
1489 GlobalUnlock(data);
1490 TRACE(" -> %s\n", debugstr_cf(ret));
1491 return ret;
1495 /**************************************************************************
1496 * export_oemtext_to_utf8
1498 * Export CF_OEMTEXT to UTF-8.
1500 static CFDataRef export_oemtext_to_utf8(HANDLE data)
1502 return export_codepage_to_utf8(data, CP_OEMCP);
1506 /**************************************************************************
1507 * export_oemtext_to_utf16
1509 * Export CF_OEMTEXT to UTF-16.
1511 static CFDataRef export_oemtext_to_utf16(HANDLE data)
1513 return export_codepage_to_utf16(data, CP_OEMCP);
1517 /**************************************************************************
1518 * export_text_to_utf8
1520 * Export CF_TEXT to UTF-8.
1522 static CFDataRef export_text_to_utf8(HANDLE data)
1524 return export_codepage_to_utf8(data, CP_ACP);
1528 /**************************************************************************
1529 * export_text_to_utf16
1531 * Export CF_TEXT to UTF-16.
1533 static CFDataRef export_text_to_utf16(HANDLE data)
1535 return export_codepage_to_utf16(data, CP_ACP);
1539 /**************************************************************************
1540 * export_unicodetext_to_utf8
1542 * Export CF_UNICODETEXT to UTF-8.
1544 static CFDataRef export_unicodetext_to_utf8(HANDLE data)
1546 CFMutableDataRef ret;
1547 LPVOID src;
1548 INT dst_len;
1550 src = GlobalLock(data);
1551 if (!src) return NULL;
1553 dst_len = WideCharToMultiByte(CP_UTF8, 0, src, -1, NULL, 0, NULL, NULL);
1554 if (dst_len) dst_len--; /* Leave off null terminator. */
1555 ret = CFDataCreateMutable(NULL, dst_len);
1556 if (ret)
1558 LPSTR dst;
1559 int i, j;
1561 CFDataSetLength(ret, dst_len);
1562 dst = (LPSTR)CFDataGetMutableBytePtr(ret);
1563 WideCharToMultiByte(CP_UTF8, 0, src, -1, dst, dst_len, NULL, NULL);
1565 /* Remove carriage returns */
1566 for (i = 0, j = 0; i < dst_len; i++)
1568 if (dst[i] == '\r' &&
1569 (i + 1 >= dst_len || dst[i + 1] == '\n' || dst[i + 1] == '\0'))
1570 continue;
1571 dst[j++] = dst[i];
1573 CFDataSetLength(ret, j);
1575 GlobalUnlock(data);
1577 return ret;
1581 /**************************************************************************
1582 * export_unicodetext_to_utf16
1584 * Export CF_UNICODETEXT to UTF-16.
1586 static CFDataRef export_unicodetext_to_utf16(HANDLE data)
1588 CFMutableDataRef ret;
1589 const WCHAR *src;
1590 INT src_len;
1592 src = GlobalLock(data);
1593 if (!src) return NULL;
1595 src_len = GlobalSize(data) / sizeof(WCHAR);
1596 if (src_len) src_len--; /* Leave off null terminator. */
1597 ret = CFDataCreateMutable(NULL, src_len * sizeof(WCHAR));
1598 if (ret)
1600 LPWSTR dst;
1601 int i, j;
1603 CFDataSetLength(ret, src_len * sizeof(WCHAR));
1604 dst = (LPWSTR)CFDataGetMutableBytePtr(ret);
1606 /* Remove carriage returns */
1607 for (i = 0, j = 0; i < src_len; i++)
1609 if (src[i] == '\r' &&
1610 (i + 1 >= src_len || src[i + 1] == '\n' || src[i + 1] == '\0'))
1611 continue;
1612 dst[j++] = src[i];
1614 CFDataSetLength(ret, j * sizeof(WCHAR));
1616 GlobalUnlock(data);
1618 return ret;
1622 /**************************************************************************
1623 * get_clipboard_info
1625 static BOOL get_clipboard_info(LPCLIPBOARDINFO cbinfo)
1627 BOOL ret = FALSE;
1629 SERVER_START_REQ(set_clipboard_info)
1631 req->flags = 0;
1633 if (wine_server_call_err(req))
1635 ERR("Failed to get clipboard owner.\n");
1637 else
1639 cbinfo->hwnd_owner = wine_server_ptr_handle(reply->old_owner);
1640 cbinfo->flags = reply->flags;
1642 ret = TRUE;
1645 SERVER_END_REQ;
1647 return ret;
1651 /**************************************************************************
1652 * release_ownership
1654 static BOOL release_ownership(void)
1656 BOOL ret = FALSE;
1658 SERVER_START_REQ(set_clipboard_info)
1660 req->flags = SET_CB_RELOWNER | SET_CB_SEQNO;
1662 if (wine_server_call_err(req))
1663 ERR("Failed to set clipboard.\n");
1664 else
1665 ret = TRUE;
1667 SERVER_END_REQ;
1669 return ret;
1673 /**************************************************************************
1674 * macdrv_get_pasteboard_data
1676 HANDLE macdrv_get_pasteboard_data(CFTypeRef pasteboard, UINT desired_format)
1678 CFArrayRef types;
1679 CFIndex count;
1680 CFIndex i;
1681 CFStringRef type, best_type;
1682 WINE_CLIPFORMAT* best_format = NULL;
1683 HANDLE data = NULL;
1685 TRACE("pasteboard %p, desired_format %s\n", pasteboard, debugstr_format(desired_format));
1687 types = macdrv_copy_pasteboard_types(pasteboard);
1688 if (!types)
1690 WARN("Failed to copy pasteboard types\n");
1691 return NULL;
1694 count = CFArrayGetCount(types);
1695 TRACE("got %ld types\n", count);
1697 for (i = 0; (!best_format || best_format->synthesized) && i < count; i++)
1699 WINE_CLIPFORMAT* format;
1701 type = CFArrayGetValueAtIndex(types, i);
1703 format = NULL;
1704 while ((!best_format || best_format->synthesized) && (format = format_for_type(format, type)))
1706 TRACE("for type %s got format %p/%s\n", debugstr_cf(type), format, debugstr_format(format ? format->format_id : 0));
1708 if (format->format_id == desired_format)
1710 /* The best format is the matching one which is not synthesized. Failing that,
1711 the best format is the first matching synthesized format. */
1712 if (!format->synthesized || !best_format)
1714 best_type = type;
1715 best_format = format;
1721 if (best_format)
1723 CFDataRef pasteboard_data = macdrv_copy_pasteboard_data(pasteboard, best_type);
1725 TRACE("got pasteboard data for type %s: %s\n", debugstr_cf(best_type), debugstr_cf(pasteboard_data));
1727 if (pasteboard_data)
1729 data = best_format->import_func(pasteboard_data);
1730 CFRelease(pasteboard_data);
1734 CFRelease(types);
1735 TRACE(" -> %p\n", data);
1736 return data;
1740 /**************************************************************************
1741 * macdrv_pasteboard_has_format
1743 BOOL macdrv_pasteboard_has_format(CFTypeRef pasteboard, UINT desired_format)
1745 CFArrayRef types;
1746 int count;
1747 UINT i;
1748 BOOL found = FALSE;
1750 TRACE("pasteboard %p, desired_format %s\n", pasteboard, debugstr_format(desired_format));
1752 types = macdrv_copy_pasteboard_types(pasteboard);
1753 if (!types)
1755 WARN("Failed to copy pasteboard types\n");
1756 return FALSE;
1759 count = CFArrayGetCount(types);
1760 TRACE("got %d types\n", count);
1762 for (i = 0; !found && i < count; i++)
1764 CFStringRef type = CFArrayGetValueAtIndex(types, i);
1765 WINE_CLIPFORMAT* format;
1767 format = NULL;
1768 while (!found && (format = format_for_type(format, type)))
1770 TRACE("for type %s got format %s\n", debugstr_cf(type), debugstr_format(format->format_id));
1772 if (format->format_id == desired_format)
1773 found = TRUE;
1777 CFRelease(types);
1778 TRACE(" -> %d\n", found);
1779 return found;
1783 /**************************************************************************
1784 * macdrv_copy_pasteboard_formats
1786 CFArrayRef macdrv_copy_pasteboard_formats(CFTypeRef pasteboard)
1788 CFArrayRef types;
1789 CFIndex count;
1790 CFMutableArrayRef formats;
1791 CFIndex i;
1792 WINE_CLIPFORMAT* format;
1794 TRACE("pasteboard %p\n", pasteboard);
1796 types = macdrv_copy_pasteboard_types(pasteboard);
1797 if (!types)
1799 WARN("Failed to copy pasteboard types\n");
1800 return NULL;
1803 count = CFArrayGetCount(types);
1804 TRACE("got %ld types\n", count);
1806 if (!count)
1808 CFRelease(types);
1809 return NULL;
1812 formats = CFArrayCreateMutable(NULL, 0, NULL);
1813 if (!formats)
1815 WARN("Failed to allocate formats array\n");
1816 CFRelease(types);
1817 return NULL;
1820 for (i = 0; i < count; i++)
1822 CFStringRef type = CFArrayGetValueAtIndex(types, i);
1823 BOOL found = FALSE;
1825 format = NULL;
1826 while ((format = format_for_type(format, type)))
1828 /* Suppose type is "public.utf8-plain-text". format->format_id will be each of
1829 CF_TEXT, CF_OEMTEXT, and CF_UNICODETEXT in turn. We want to look up the natural
1830 type for each of those IDs (e.g. CF_TEXT -> "org.winehq.builtin.text") and then see
1831 if that type is present in the pasteboard. If it is, then we don't want to add the
1832 format to the list yet because it would be out of order.
1834 For example, if a Mac app put "public.utf8-plain-text" and "public.tiff" on the
1835 pasteboard, then we want the Win32 clipboard formats to be CF_TEXT, CF_OEMTEXT, and
1836 CF_UNICODETEXT, and CF_TIFF, in that order. All of the text formats belong before
1837 CF_TIFF because the Mac app expressed that text was "better" than the TIFF. In
1838 this case, as soon as we encounter "public.utf8-plain-text" we should add all of
1839 the associated text format IDs.
1841 But if a Wine process put "org.winehq.builtin.unicodetext",
1842 "public.utf8-plain-text", "public.utf16-plain-text", and "public.tiff", then we
1843 want the clipboard formats to be CF_UNICODETEXT, CF_TIFF, CF_TEXT, and CF_OEMTEXT,
1844 in that order. The Windows program presumably added CF_UNICODETEXT and CF_TIFF.
1845 We're synthesizing CF_TEXT and CF_OEMTEXT from CF_UNICODETEXT but we want them to
1846 come after the non-synthesized CF_TIFF. In this case, we don't want to add the
1847 text formats upon encountering "public.utf8-plain-text",
1849 We tell the two cases apart by seeing that one of the natural types for the text
1850 formats (i.e. "org.winehq.builtin.unicodetext") is present on the pasteboard.
1851 "found" indicates that. */
1853 if (!format->synthesized)
1855 TRACE("for type %s got primary format %p/%s\n", debugstr_cf(type), format, debugstr_format(format->format_id));
1856 CFArrayAppendValue(formats, (void*)format->format_id);
1857 found = TRUE;
1859 else if (!found && format->natural_format &&
1860 CFArrayContainsValue(types, CFRangeMake(0, count), format->natural_format->type))
1862 TRACE("for type %s deferring synthesized formats because type %s is also present\n",
1863 debugstr_cf(type), debugstr_cf(format->natural_format->type));
1864 found = TRUE;
1868 if (!found)
1870 while ((format = format_for_type(format, type)))
1872 /* Don't override a real value with a synthesized value. */
1873 if (!CFArrayContainsValue(formats, CFRangeMake(0, CFArrayGetCount(formats)), (void*)format->format_id))
1875 TRACE("for type %s got synthesized format %p/%s\n", debugstr_cf(type), format, debugstr_format(format->format_id));
1876 CFArrayAppendValue(formats, (void*)format->format_id);
1882 /* Now go back through the types adding the synthesized formats that we deferred before. */
1883 for (i = 0; i < count; i++)
1885 CFStringRef type = CFArrayGetValueAtIndex(types, i);
1887 format = NULL;
1888 while ((format = format_for_type(format, type)))
1890 if (format->synthesized)
1892 /* Don't override a real value with a synthesized value. */
1893 if (!CFArrayContainsValue(formats, CFRangeMake(0, CFArrayGetCount(formats)), (void*)format->format_id))
1895 TRACE("for type %s got synthesized format %p/%s\n", debugstr_cf(type), format, debugstr_format(format->format_id));
1896 CFArrayAppendValue(formats, (void*)format->format_id);
1902 CFRelease(types);
1904 TRACE(" -> %s\n", debugstr_cf(formats));
1905 return formats;
1909 /**************************************************************************
1910 * check_clipboard_ownership
1912 static void check_clipboard_ownership(HWND *owner)
1914 CLIPBOARDINFO cbinfo;
1916 if (owner) *owner = NULL;
1918 /* If Wine thinks we're the clipboard owner but Mac OS X thinks we're not
1919 the pasteboard owner, update Wine. */
1920 if (get_clipboard_info(&cbinfo) && (cbinfo.flags & CB_PROCESS))
1922 if (!(cbinfo.flags & CB_OPEN) && !macdrv_is_pasteboard_owner())
1924 TRACE("Lost clipboard ownership\n");
1926 if (OpenClipboard(cbinfo.hwnd_owner))
1928 /* Destroy private objects */
1929 SendMessageW(cbinfo.hwnd_owner, WM_DESTROYCLIPBOARD, 0, 0);
1931 /* Give up ownership of the windows clipboard */
1932 release_ownership();
1933 CloseClipboard();
1936 else if (owner)
1937 *owner = cbinfo.hwnd_owner;
1942 /**************************************************************************
1943 * Mac User Driver Clipboard Exports
1944 **************************************************************************/
1947 /**************************************************************************
1948 * CountClipboardFormats (MACDRV.@)
1950 INT CDECL macdrv_CountClipboardFormats(void)
1952 CFMutableSetRef seen_formats;
1953 CFArrayRef types;
1954 CFIndex count;
1955 CFIndex i;
1956 INT ret = 0;
1958 TRACE("()\n");
1959 check_clipboard_ownership(NULL);
1961 seen_formats = CFSetCreateMutable(NULL, 0, NULL);
1962 if (!seen_formats)
1964 WARN("Failed to allocate set to track seen formats\n");
1965 return 0;
1968 types = macdrv_copy_pasteboard_types(NULL);
1969 if (!types)
1971 WARN("Failed to copy pasteboard types\n");
1972 CFRelease(seen_formats);
1973 return 0;
1976 count = CFArrayGetCount(types);
1977 TRACE("got %ld types\n", count);
1979 for (i = 0; i < count; i++)
1981 CFStringRef type = CFArrayGetValueAtIndex(types, i);
1982 WINE_CLIPFORMAT* format;
1984 format = NULL;
1985 while ((format = format_for_type(format, type)))
1987 TRACE("for type %s got format %p/%s\n", debugstr_cf(type), format, debugstr_format(format->format_id));
1989 if (!CFSetContainsValue(seen_formats, (void*)format->format_id))
1991 ret++;
1992 CFSetAddValue(seen_formats, (void*)format->format_id);
1997 CFRelease(types);
1998 CFRelease(seen_formats);
1999 TRACE(" -> %d\n", ret);
2000 return ret;
2004 /**************************************************************************
2005 * EmptyClipboard (MACDRV.@)
2007 * Empty cached clipboard data.
2009 void CDECL macdrv_EmptyClipboard(void)
2011 TRACE("()\n");
2012 check_clipboard_ownership(NULL);
2013 macdrv_clear_pasteboard();
2017 /**************************************************************************
2018 * EndClipboardUpdate (MACDRV.@)
2020 void CDECL macdrv_EndClipboardUpdate(void)
2022 TRACE("()\n");
2023 check_clipboard_ownership(NULL);
2027 /**************************************************************************
2028 * EnumClipboardFormats (MACDRV.@)
2030 UINT CDECL macdrv_EnumClipboardFormats(UINT prev_format)
2032 CFArrayRef formats;
2033 CFIndex count;
2034 CFIndex i;
2035 UINT ret = 0;
2037 TRACE("prev_format %s\n", debugstr_format(prev_format));
2038 check_clipboard_ownership(NULL);
2040 formats = macdrv_copy_pasteboard_formats(NULL);
2041 if (formats)
2043 count = CFArrayGetCount(formats);
2044 if (prev_format)
2046 i = CFArrayGetFirstIndexOfValue(formats, CFRangeMake(0, count), (void*)prev_format);
2047 if (i != kCFNotFound)
2048 i++;
2050 else
2051 i = 0;
2053 if (i != kCFNotFound && i < count)
2054 ret = (UINT)CFArrayGetValueAtIndex(formats, i);
2056 CFRelease(formats);
2059 TRACE(" -> %u\n", ret);
2060 return ret;
2064 /**************************************************************************
2065 * GetClipboardData (MACDRV.@)
2067 HANDLE CDECL macdrv_GetClipboardData(UINT desired_format)
2069 check_clipboard_ownership(NULL);
2071 return macdrv_get_pasteboard_data(NULL, desired_format);
2075 /**************************************************************************
2076 * IsClipboardFormatAvailable (MACDRV.@)
2078 BOOL CDECL macdrv_IsClipboardFormatAvailable(UINT desired_format)
2080 check_clipboard_ownership(NULL);
2081 return macdrv_pasteboard_has_format(NULL, desired_format);
2085 /**************************************************************************
2086 * SetClipboardData (MACDRV.@)
2088 BOOL CDECL macdrv_SetClipboardData(UINT format_id, HANDLE data, BOOL owner)
2090 HWND hwnd_owner;
2091 macdrv_window window;
2092 WINE_CLIPFORMAT *format;
2093 CFDataRef cfdata = NULL;
2095 check_clipboard_ownership(&hwnd_owner);
2096 window = macdrv_get_cocoa_window(GetAncestor(hwnd_owner, GA_ROOT), FALSE);
2097 TRACE("format_id %s data %p owner %d hwnd_owner %p window %p)\n", debugstr_format(format_id), data, owner, hwnd_owner, window);
2099 format = natural_format_for_format(format_id);
2100 if (!format && !(format = insert_clipboard_format(format_id, NULL)))
2102 WARN("Failed to register clipboard format %s\n", debugstr_format(format_id));
2103 return FALSE;
2106 /* Export the data to the Mac pasteboard. */
2107 if (data)
2109 if (!format->export_func || !(cfdata = format->export_func(data)))
2111 WARN("Failed to export %s data to type %s\n", debugstr_format(format_id), debugstr_cf(format->type));
2112 return FALSE;
2116 if (macdrv_set_pasteboard_data(format->type, cfdata, window))
2117 TRACE("Set pasteboard data for type %s: %s\n", debugstr_cf(format->type), debugstr_cf(cfdata));
2118 else
2120 WARN("Failed to set pasteboard data for type %s: %s\n", debugstr_cf(format->type), debugstr_cf(cfdata));
2121 if (cfdata) CFRelease(cfdata);
2122 return FALSE;
2125 if (cfdata) CFRelease(cfdata);
2127 /* Find any other formats for this format_id (the exportable synthesized ones). */
2128 LIST_FOR_EACH_ENTRY(format, &format_list, WINE_CLIPFORMAT, entry)
2130 if (format->format_id == format_id && format->synthesized && format->export_func)
2132 /* We have a synthesized format for this format ID. Add its type to the pasteboard. */
2133 TRACE("Synthesized from format %s: type %s\n", debugstr_format(format_id), debugstr_cf(format->type));
2135 if (data)
2137 cfdata = format->export_func(data);
2138 if (!cfdata)
2140 WARN("Failed to export %s data to type %s\n", debugstr_format(format->format_id), debugstr_cf(format->type));
2141 continue;
2144 else
2145 cfdata = NULL;
2147 if (macdrv_set_pasteboard_data(format->type, cfdata, window))
2148 TRACE(" ... set pasteboard data: %s\n", debugstr_cf(cfdata));
2149 else
2150 WARN(" ... failed to set pasteboard data: %s\n", debugstr_cf(cfdata));
2152 if (cfdata) CFRelease(cfdata);
2156 if (data)
2158 /* FIXME: According to MSDN, the caller is entitled to lock and read from
2159 data until CloseClipboard is called. So, we should defer this cleanup. */
2160 if ((format_id >= CF_GDIOBJFIRST && format_id <= CF_GDIOBJLAST) ||
2161 format_id == CF_BITMAP ||
2162 format_id == CF_DIB ||
2163 format_id == CF_PALETTE)
2165 DeleteObject(data);
2167 else if (format_id == CF_METAFILEPICT)
2169 DeleteMetaFile(((METAFILEPICT *)GlobalLock(data))->hMF);
2170 GlobalFree(data);
2172 else if (format_id == CF_ENHMETAFILE)
2174 DeleteEnhMetaFile(data);
2176 else if (format_id < CF_PRIVATEFIRST || CF_PRIVATELAST < format_id)
2178 GlobalFree(data);
2182 return TRUE;
2186 /**************************************************************************
2187 * MACDRV Private Clipboard Exports
2188 **************************************************************************/
2191 /**************************************************************************
2192 * macdrv_clipboard_process_attach
2194 void macdrv_clipboard_process_attach(void)
2196 UINT i;
2197 WINE_CLIPFORMAT *format;
2199 /* Register built-in formats */
2200 for (i = 0; i < sizeof(builtin_format_ids)/sizeof(builtin_format_ids[0]); i++)
2202 if (!(format = HeapAlloc(GetProcessHeap(), 0, sizeof(*format)))) break;
2203 format->format_id = builtin_format_ids[i].id;
2204 format->type = CFRetain(builtin_format_ids[i].type);
2205 format->import_func = builtin_format_ids[i].import;
2206 format->export_func = builtin_format_ids[i].export;
2207 format->synthesized = builtin_format_ids[i].synthesized;
2208 format->natural_format = NULL;
2209 list_add_tail(&format_list, &format->entry);
2212 LIST_FOR_EACH_ENTRY(format, &format_list, WINE_CLIPFORMAT, entry)
2214 if (format->synthesized)
2215 format->natural_format = natural_format_for_format(format->format_id);
2218 /* Register known mappings between Windows formats and Mac types */
2219 for (i = 0; i < sizeof(builtin_format_names)/sizeof(builtin_format_names[0]); i++)
2221 if (!(format = HeapAlloc(GetProcessHeap(), 0, sizeof(*format)))) break;
2222 format->format_id = RegisterClipboardFormatW(builtin_format_names[i].name);
2223 format->type = CFRetain(builtin_format_names[i].type);
2224 format->import_func = builtin_format_names[i].import;
2225 format->export_func = builtin_format_names[i].export;
2226 format->synthesized = FALSE;
2227 format->natural_format = NULL;
2228 list_add_tail(&format_list, &format->entry);
2233 /**************************************************************************
2234 * query_pasteboard_data
2236 BOOL query_pasteboard_data(HWND hwnd, CFStringRef type)
2238 BOOL ret = FALSE;
2239 CLIPBOARDINFO cbinfo;
2240 WINE_CLIPFORMAT* format;
2241 CFArrayRef types = NULL;
2242 CFRange range;
2244 TRACE("hwnd %p type %s\n", hwnd, debugstr_cf(type));
2246 if (get_clipboard_info(&cbinfo))
2247 hwnd = cbinfo.hwnd_owner;
2249 format = NULL;
2250 while ((format = format_for_type(format, type)))
2252 TRACE("for type %s got format %p/%s\n", debugstr_cf(type), format, debugstr_format(format->format_id));
2254 if (!format->synthesized)
2256 TRACE("Sending WM_RENDERFORMAT message for format %s to hwnd %p\n", debugstr_format(format->format_id), hwnd);
2257 SendMessageW(hwnd, WM_RENDERFORMAT, format->format_id, 0);
2258 ret = TRUE;
2259 goto done;
2262 if (!types)
2264 types = macdrv_copy_pasteboard_types(NULL);
2265 if (!types)
2267 WARN("Failed to copy pasteboard types\n");
2268 break;
2271 range = CFRangeMake(0, CFArrayGetCount(types));
2274 /* The type maps to a synthesized format. Now look up what type that format maps to natively
2275 (not synthesized). For example, if type is "public.utf8-plain-text", then this format may
2276 have an ID of CF_TEXT. From CF_TEXT, we want to find "org.winehq.builtin.text" to see if
2277 that type is present in the pasteboard. If it is, then the app must have promised it and
2278 we can ask it to render it. (If it had put it on the clipboard immediately, then the
2279 pasteboard would also have data for "public.utf8-plain-text" and we wouldn't be here.) If
2280 "org.winehq.builtin.text" is not on the pasteboard, then one of the other text formats is
2281 presumably responsible for the promise that we're trying to satisfy, so we keep looking. */
2282 if (format->natural_format && CFArrayContainsValue(types, range, format->natural_format->type))
2284 TRACE("Sending WM_RENDERFORMAT message for format %s to hwnd %p\n", debugstr_format(format->format_id), hwnd);
2285 SendMessageW(hwnd, WM_RENDERFORMAT, format->format_id, 0);
2286 ret = TRUE;
2287 goto done;
2291 done:
2292 if (types) CFRelease(types);
2294 return ret;