mshtml: Use lazy allocation for connection points.
[wine] / dlls / winemac.drv / clipboard.c
1 /*
2  * Mac clipboard driver
3  *
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.
9  *
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.
14  *
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.
19  *
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
23  */
24
25 #include "config.h"
26
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"
34
35
36 WINE_DEFAULT_DEBUG_CHANNEL(clipboard);
37
38
39 /**************************************************************************
40  *              Types
41  **************************************************************************/
42
43 typedef struct
44 {
45     HWND hwnd_owner;
46     UINT flags;
47 } CLIPBOARDINFO, *LPCLIPBOARDINFO;
48
49 typedef HANDLE (*DRVIMPORTFUNC)(CFDataRef data);
50 typedef CFDataRef (*DRVEXPORTFUNC)(HANDLE data);
51
52 typedef struct
53 {
54     struct list     entry;
55     UINT            format_id;
56     CFStringRef     type;
57     DRVIMPORTFUNC   import_func;
58     DRVEXPORTFUNC   export_func;
59     BOOL            synthesized;
60 } WINE_CLIPFORMAT;
61
62
63 /**************************************************************************
64  *              Constants
65  **************************************************************************/
66
67
68 /**************************************************************************
69  *              Forward Function Declarations
70  **************************************************************************/
71
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);
85
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);
93
94
95 /**************************************************************************
96  *              Static Variables
97  **************************************************************************/
98
99 /* Clipboard formats */
100 static struct list format_list = LIST_INIT(format_list);
101
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
104     types.
105
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.
113
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.
117
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.
121
122     Summary:
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;
128                                             maps to <Mac type>
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>
141 */
142
143 static const struct
144 {
145     UINT          id;
146     CFStringRef   type;
147     DRVIMPORTFUNC import;
148     DRVEXPORTFUNC export;
149     BOOL          synthesized;
150 } builtin_format_ids[] =
151 {
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 },
166
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 },
170
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 },
174
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 },
178
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 },
182
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 },
185
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 },
188
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 },
191 };
192
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};
198 static const struct
199 {
200     LPCWSTR     name;
201     CFStringRef type;
202 } builtin_format_names[] =
203 {
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") },
209 };
210
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};
213
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.");
216
217
218 /**************************************************************************
219  *              Internal Clipboard implementation methods
220  **************************************************************************/
221
222 /*
223  * format_list functions
224  */
225
226 /**************************************************************************
227  *              debugstr_format
228  */
229 const char *debugstr_format(UINT id)
230 {
231     WCHAR buffer[256];
232
233     if (GetClipboardFormatNameW(id, buffer, 256))
234         return wine_dbg_sprintf("0x%04x %s", id, debugstr_w(buffer));
235
236     switch (id)
237     {
238 #define BUILTIN(id) case id: return #id;
239     BUILTIN(CF_TEXT)
240     BUILTIN(CF_BITMAP)
241     BUILTIN(CF_METAFILEPICT)
242     BUILTIN(CF_SYLK)
243     BUILTIN(CF_DIF)
244     BUILTIN(CF_TIFF)
245     BUILTIN(CF_OEMTEXT)
246     BUILTIN(CF_DIB)
247     BUILTIN(CF_PALETTE)
248     BUILTIN(CF_PENDATA)
249     BUILTIN(CF_RIFF)
250     BUILTIN(CF_WAVE)
251     BUILTIN(CF_UNICODETEXT)
252     BUILTIN(CF_ENHMETAFILE)
253     BUILTIN(CF_HDROP)
254     BUILTIN(CF_LOCALE)
255     BUILTIN(CF_DIBV5)
256     BUILTIN(CF_OWNERDISPLAY)
257     BUILTIN(CF_DSPTEXT)
258     BUILTIN(CF_DSPBITMAP)
259     BUILTIN(CF_DSPMETAFILEPICT)
260     BUILTIN(CF_DSPENHMETAFILE)
261 #undef BUILTIN
262     default: return wine_dbg_sprintf("0x%04x", id);
263     }
264 }
265
266
267 /**************************************************************************
268  *              insert_clipboard_format
269  */
270 static WINE_CLIPFORMAT *insert_clipboard_format(UINT id, CFStringRef type)
271 {
272     WINE_CLIPFORMAT *format;
273
274     format = HeapAlloc(GetProcessHeap(), 0, sizeof(*format));
275
276     if (format == NULL)
277     {
278         WARN("No more memory for a new format!\n");
279         return NULL;
280     }
281     format->format_id = id;
282     format->import_func = import_clipboard_data;
283     format->export_func = export_clipboard_data;
284     format->synthesized = FALSE;
285
286     if (type)
287         format->type = CFStringCreateCopy(NULL, type);
288     else
289     {
290         WCHAR buffer[256];
291
292         GetClipboardFormatNameW(format->format_id, buffer, 256);
293         if (!strncmpW(buffer, mac_type_name_prefix, strlenW(mac_type_name_prefix)))
294         {
295             const WCHAR *p = buffer + strlenW(mac_type_name_prefix);
296             format->type = CFStringCreateWithCharacters(NULL, (UniChar*)p, strlenW(p));
297         }
298         else
299         {
300             format->type = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%S"),
301                                                     registered_name_type_prefix, buffer);
302         }
303     }
304
305     list_add_tail(&format_list, &format->entry);
306
307     TRACE("Registering format %s type %s\n", debugstr_format(format->format_id),
308           debugstr_cf(format->type));
309
310     return format;
311 }
312
313
314 /**************************************************************************
315  *              register_format
316  *
317  * Register a custom Mac clipboard format.
318  */
319 static WINE_CLIPFORMAT* register_format(UINT id, CFStringRef type)
320 {
321     WINE_CLIPFORMAT *format;
322
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;
326
327     return insert_clipboard_format(id, type);
328 }
329
330
331 /**************************************************************************
332  *              format_for_type
333  */
334 static WINE_CLIPFORMAT* format_for_type(WINE_CLIPFORMAT *current, CFStringRef type)
335 {
336     struct list *ptr = current ? &current->entry : &format_list;
337     WINE_CLIPFORMAT *format = NULL;
338
339     TRACE("current %p/%s type %s\n", current, debugstr_format(current ? current->format_id : 0), debugstr_cf(type));
340
341     while ((ptr = list_next(&format_list, ptr)))
342     {
343         format = LIST_ENTRY(ptr, WINE_CLIPFORMAT, entry);
344         if (CFEqual(format->type, type))
345         {
346             TRACE(" -> %p/%s\n", format, debugstr_format(format->format_id));
347             return format;
348         }
349     }
350
351     if (!current)
352     {
353         LPWSTR name;
354
355         if (CFStringHasPrefix(type, CFSTR("org.winehq.builtin.")))
356         {
357             ERR("Shouldn't happen. Built-in type %s should have matched something in format list.\n",
358                 debugstr_cf(type));
359             return NULL;
360         }
361         else if (CFStringHasPrefix(type, registered_name_type_prefix))
362         {
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),
366                                   (UniChar*)name);
367             name[len] = 0;
368         }
369         else
370         {
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));
376             name[len] = 0;
377         }
378
379         format = register_format(RegisterClipboardFormatW(name), type);
380         if (!format)
381             ERR("Failed to register format for type %s name %s\n", debugstr_cf(type), debugstr_w(name));
382
383         HeapFree(GetProcessHeap(), 0, name);
384     }
385
386     TRACE(" -> %p/%s\n", format, debugstr_format(format ? format->format_id : 0));
387     return format;
388 }
389
390
391 /**************************************************************************
392  *              convert_text
393  *
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
396  *  characters.
397  */
398 static HANDLE convert_text(const void *src, int src_len, UINT src_cp, UINT dest_cp)
399 {
400     HANDLE ret = NULL;
401     const WCHAR *wstr;
402     int wstr_len;
403     HANDLE handle;
404     char *p;
405
406     if (src_cp == (UINT)-1)
407     {
408         wstr = src;
409         wstr_len = src_len / sizeof(WCHAR);
410     }
411     else
412     {
413         WCHAR *temp;
414
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;
420         wstr = temp;
421     }
422
423     if (dest_cp == (UINT)-1)
424     {
425         handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, wstr_len * sizeof(WCHAR));
426         if (handle && (p = GlobalLock(handle)))
427         {
428             memcpy(p, wstr, wstr_len * sizeof(WCHAR));
429             GlobalUnlock(handle);
430             ret = handle;
431         }
432     }
433     else
434     {
435         INT len;
436
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);
440
441         if (handle && (p = GlobalLock(handle)))
442         {
443             WideCharToMultiByte(dest_cp, 0, wstr, wstr_len, p, len, NULL, NULL);
444             p[len - 1] = 0;
445             GlobalUnlock(handle);
446             ret = handle;
447         }
448     }
449
450     return ret;
451 }
452
453
454 /**************************************************************************
455  *              convert_unicodetext_to_codepage
456  */
457 static HANDLE convert_unicodetext_to_codepage(HANDLE unicode_handle, UINT cp)
458 {
459     LPWSTR unicode_string = GlobalLock(unicode_handle);
460     HANDLE ret = NULL;
461
462     if (unicode_string)
463     {
464         ret = convert_text(unicode_string, GlobalSize(unicode_handle), -1, cp);
465         GlobalUnlock(unicode_handle);
466     }
467
468     return ret;
469 }
470
471
472 /***********************************************************************
473  *              bitmap_info_size
474  *
475  * Return the size of the bitmap info structure including color table.
476  */
477 static int bitmap_info_size(const BITMAPINFO *info, WORD coloruse)
478 {
479     unsigned int colors, size, masks = 0;
480
481     if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
482     {
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));
487     }
488     else  /* assume BITMAPINFOHEADER */
489     {
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));
496     }
497 }
498
499
500 /***********************************************************************
501  *              create_dib_from_bitmap
502  *
503  * Allocates a packed DIB and copies the bitmap data into it.
504  */
505 static HGLOBAL create_dib_from_bitmap(HBITMAP hBmp)
506 {
507     BITMAP bmp;
508     HDC hdc;
509     HGLOBAL hPackedDIB;
510     LPBYTE pPackedDIB;
511     LPBITMAPINFOHEADER pbmiHeader;
512     unsigned int cDataSize, cPackedSize, OffsetBits;
513     int nLinesCopied;
514
515     if (!GetObjectW(hBmp, sizeof(bmp), &bmp)) return 0;
516
517     /*
518      * A packed DIB contains a BITMAPINFO structure followed immediately by
519      * an optional color palette and the pixel data.
520      */
521
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)
526                   + cDataSize;
527     /* Get the offset to the bits */
528     OffsetBits = cPackedSize - cDataSize;
529
530     /* Allocate the packed DIB */
531     TRACE("\tAllocating packed DIB of size %d\n", cPackedSize);
532     hPackedDIB = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, cPackedSize);
533     if (!hPackedDIB)
534     {
535         WARN("Could not allocate packed DIB!\n");
536         return 0;
537     }
538
539     /* A packed DIB starts with a BITMAPINFOHEADER */
540     pPackedDIB = GlobalLock(hPackedDIB);
541     pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
542
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;
554
555     /* Retrieve the DIB bits from the bitmap and fill in the
556      * DIB color table if present */
557     hdc = GetDC(0);
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);
566     ReleaseDC(0, hdc);
567
568     /* Cleanup if GetDIBits failed */
569     if (nLinesCopied != bmp.bmHeight)
570     {
571         TRACE("\tGetDIBits returned %d. Actual lines=%d\n", nLinesCopied, bmp.bmHeight);
572         GlobalFree(hPackedDIB);
573         hPackedDIB = 0;
574     }
575     return hPackedDIB;
576 }
577
578
579 /**************************************************************************
580  *              import_clipboard_data
581  *
582  *  Generic import clipboard data routine.
583  */
584 static HANDLE import_clipboard_data(CFDataRef data)
585 {
586     HANDLE data_handle = NULL;
587
588     size_t len = CFDataGetLength(data);
589     if (len)
590     {
591         LPVOID p;
592
593         /* Turn on the DDESHARE flag to enable shared 32 bit memory */
594         data_handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, len);
595         if (!data_handle)
596             return NULL;
597
598         if ((p = GlobalLock(data_handle)))
599         {
600             memcpy(p, CFDataGetBytePtr(data), len);
601             GlobalUnlock(data_handle);
602         }
603         else
604         {
605             GlobalFree(data_handle);
606             data_handle = NULL;
607         }
608     }
609
610     return data_handle;
611 }
612
613
614 /**************************************************************************
615  *              import_bmp_to_bitmap
616  *
617  *  Import BMP data, converting to CF_BITMAP format.
618  */
619 static HANDLE import_bmp_to_bitmap(CFDataRef data)
620 {
621     HANDLE ret = 0;
622     HANDLE dib = import_bmp_to_dib(data);
623     BITMAPINFO *bmi;
624
625     if (dib && (bmi = GlobalLock(dib)))
626     {
627         HDC hdc;
628         unsigned int offset;
629
630         hdc = GetDC(NULL);
631
632         offset = bitmap_info_size(bmi, DIB_RGB_COLORS);
633
634         ret = CreateDIBitmap(hdc, &bmi->bmiHeader, CBM_INIT, (LPBYTE)bmi + offset,
635                              bmi, DIB_RGB_COLORS);
636
637         GlobalUnlock(dib);
638         ReleaseDC(NULL, hdc);
639     }
640
641     GlobalFree(dib);
642     return ret;
643 }
644
645
646 /**************************************************************************
647  *              import_bmp_to_dib
648  *
649  *  Import BMP data, converting to CF_DIB format.  This just entails
650  *  stripping the BMP file format header.
651  */
652 static HANDLE import_bmp_to_dib(CFDataRef data)
653 {
654     HANDLE ret = 0;
655     BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)CFDataGetBytePtr(data);
656     CFIndex len = CFDataGetLength(data);
657
658     if (len >= sizeof(*bfh) + sizeof(BITMAPCOREHEADER) &&
659         bfh->bfType == 0x4d42 /* "BM" */)
660     {
661         BITMAPINFO *bmi = (BITMAPINFO*)(bfh + 1);
662         BYTE* p;
663
664         len -= sizeof(*bfh);
665         ret = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, len);
666         if (!ret || !(p = GlobalLock(ret)))
667         {
668             GlobalFree(ret);
669             return 0;
670         }
671
672         memcpy(p, bmi, len);
673         GlobalUnlock(ret);
674     }
675
676     return ret;
677 }
678
679
680 /**************************************************************************
681  *              import_nsfilenames_to_hdrop
682  *
683  *  Import NSFilenamesPboardType data, converting the property-list-
684  *  serialized array of path strings to CF_HDROP.
685  */
686 static HANDLE import_nsfilenames_to_hdrop(CFDataRef data)
687 {
688     HDROP hdrop = NULL;
689     CFArrayRef names;
690     CFIndex count, i;
691     size_t len;
692     char *buffer = NULL;
693     WCHAR **paths = NULL;
694     DROPFILES* dropfiles;
695     UniChar* p;
696
697     TRACE("data %s\n", debugstr_cf(data));
698
699     names = (CFArrayRef)CFPropertyListCreateWithData(NULL, data, kCFPropertyListImmutable,
700                                                      NULL, NULL);
701     if (!names || CFGetTypeID(names) != CFArrayGetTypeID())
702     {
703         WARN("failed to interpret data as a CFArray\n");
704         goto done;
705     }
706
707     count = CFArrayGetCount(names);
708
709     len = 0;
710     for (i = 0; i < count; i++)
711     {
712         CFIndex this_len;
713         CFStringRef name = (CFStringRef)CFArrayGetValueAtIndex(names, i);
714         TRACE("    %s\n", debugstr_cf(name));
715         if (CFGetTypeID(name) != CFStringGetTypeID())
716         {
717             WARN("non-string in array\n");
718             goto done;
719         }
720
721         this_len = CFStringGetMaximumSizeOfFileSystemRepresentation(name);
722         if (this_len > len)
723             len = this_len;
724     }
725
726     buffer = HeapAlloc(GetProcessHeap(), 0, len);
727     if (!buffer)
728     {
729         WARN("failed to allocate buffer for file-system representations\n");
730         goto done;
731     }
732
733     paths = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, count * sizeof(paths[0]));
734     if (!paths)
735     {
736         WARN("failed to allocate array of DOS paths\n");
737         goto done;
738     }
739
740     for (i = 0; i < count; i++)
741     {
742         CFStringRef name = (CFStringRef)CFArrayGetValueAtIndex(names, i);
743         if (!CFStringGetFileSystemRepresentation(name, buffer, len))
744         {
745             WARN("failed to get file-system representation for %s\n", debugstr_cf(name));
746             goto done;
747         }
748         paths[i] = wine_get_dos_file_name(buffer);
749         if (!paths[i])
750         {
751             WARN("failed to get DOS path for %s\n", debugstr_a(buffer));
752             goto done;
753         }
754     }
755
756     len = 1; /* for the terminating null */
757     for (i = 0; i < count; i++)
758         len += strlenW(paths[i]) + 1;
759
760     hdrop = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, sizeof(*dropfiles) + len * sizeof(WCHAR));
761     if (!hdrop || !(dropfiles = GlobalLock(hdrop)))
762     {
763         WARN("failed to allocate HDROP\n");
764         GlobalFree(hdrop);
765         hdrop = NULL;
766         goto done;
767     }
768
769     dropfiles->pFiles   = sizeof(*dropfiles);
770     dropfiles->pt.x     = 0;
771     dropfiles->pt.y     = 0;
772     dropfiles->fNC      = FALSE;
773     dropfiles->fWide    = TRUE;
774
775     p = (WCHAR*)(dropfiles + 1);
776     for (i = 0; i < count; i++)
777     {
778         strcpyW(p, paths[i]);
779         p += strlenW(p) + 1;
780     }
781     *p = 0;
782
783     GlobalUnlock(hdrop);
784
785 done:
786     if (paths)
787     {
788         for (i = 0; i < count; i++)
789             HeapFree(GetProcessHeap(), 0, paths[i]);
790         HeapFree(GetProcessHeap(), 0, paths);
791     }
792     HeapFree(GetProcessHeap(), 0, buffer);
793     if (names) CFRelease(names);
794     return hdrop;
795 }
796
797
798 /**************************************************************************
799  *              import_oemtext_to_text
800  *
801  *  Import CF_OEMTEXT data, converting the string to CF_TEXT.
802  */
803 static HANDLE import_oemtext_to_text(CFDataRef data)
804 {
805     return convert_text(CFDataGetBytePtr(data), CFDataGetLength(data), CP_OEMCP, CP_ACP);
806 }
807
808
809 /**************************************************************************
810  *              import_oemtext_to_unicodetext
811  *
812  *  Import CF_OEMTEXT data, converting the string to CF_UNICODETEXT.
813  */
814 static HANDLE import_oemtext_to_unicodetext(CFDataRef data)
815 {
816     return convert_text(CFDataGetBytePtr(data), CFDataGetLength(data), CP_OEMCP, -1);
817 }
818
819
820 /**************************************************************************
821  *              import_text_to_oemtext
822  *
823  *  Import CF_TEXT data, converting the string to CF_OEMTEXT.
824  */
825 static HANDLE import_text_to_oemtext(CFDataRef data)
826 {
827     return convert_text(CFDataGetBytePtr(data), CFDataGetLength(data), CP_ACP, CP_OEMCP);
828 }
829
830
831 /**************************************************************************
832  *              import_text_to_unicodetext
833  *
834  *  Import CF_TEXT data, converting the string to CF_UNICODETEXT.
835  */
836 static HANDLE import_text_to_unicodetext(CFDataRef data)
837 {
838     return convert_text(CFDataGetBytePtr(data), CFDataGetLength(data), CP_ACP, -1);
839 }
840
841
842 /**************************************************************************
843  *              import_unicodetext_to_oemtext
844  *
845  *  Import a CF_UNICODETEXT string, converting the string to CF_OEMTEXT.
846  */
847 static HANDLE import_unicodetext_to_oemtext(CFDataRef data)
848 {
849     return convert_text(CFDataGetBytePtr(data), CFDataGetLength(data), -1, CP_OEMCP);
850 }
851
852
853 /**************************************************************************
854  *              import_unicodetext_to_text
855  *
856  *  Import a CF_UNICODETEXT string, converting the string to CF_TEXT.
857  */
858 static HANDLE import_unicodetext_to_text(CFDataRef data)
859 {
860     return convert_text(CFDataGetBytePtr(data), CFDataGetLength(data), -1, CP_ACP);
861 }
862
863
864 /**************************************************************************
865  *              import_utf8_to_oemtext
866  *
867  *  Import a UTF-8 string, converting the string to CF_OEMTEXT.
868  */
869 static HANDLE import_utf8_to_oemtext(CFDataRef data)
870 {
871     HANDLE unicode_handle = import_utf8_to_unicodetext(data);
872     HANDLE ret = convert_unicodetext_to_codepage(unicode_handle, CP_OEMCP);
873
874     GlobalFree(unicode_handle);
875     return ret;
876 }
877
878
879 /**************************************************************************
880  *              import_utf8_to_text
881  *
882  *  Import a UTF-8 string, converting the string to CF_TEXT.
883  */
884 static HANDLE import_utf8_to_text(CFDataRef data)
885 {
886     HANDLE unicode_handle = import_utf8_to_unicodetext(data);
887     HANDLE ret = convert_unicodetext_to_codepage(unicode_handle, CP_ACP);
888
889     GlobalFree(unicode_handle);
890     return ret;
891 }
892
893
894 /**************************************************************************
895  *              import_utf8_to_unicodetext
896  *
897  *  Import a UTF-8 string, converting the string to CF_UNICODETEXT.
898  */
899 static HANDLE import_utf8_to_unicodetext(CFDataRef data)
900 {
901     const BYTE *src;
902     unsigned long data_len;
903     unsigned long new_lines = 0;
904     LPSTR dst;
905     unsigned long i, j;
906     HANDLE unicode_handle = NULL;
907
908     src = CFDataGetBytePtr(data);
909     data_len = CFDataGetLength(data);
910     for (i = 0; i < data_len; i++)
911     {
912         if (src[i] == '\n')
913             new_lines++;
914     }
915
916     if ((dst = HeapAlloc(GetProcessHeap(), 0, data_len + new_lines + 1)))
917     {
918         UINT count;
919
920         for (i = 0, j = 0; i < data_len; i++)
921         {
922             if (src[i] == '\n')
923                 dst[j++] = '\r';
924
925             dst[j++] = src[i];
926         }
927         dst[j] = 0;
928
929         count = MultiByteToWideChar(CP_UTF8, 0, dst, -1, NULL, 0);
930         unicode_handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, count * sizeof(WCHAR));
931
932         if (unicode_handle)
933         {
934             WCHAR *textW = GlobalLock(unicode_handle);
935             MultiByteToWideChar(CP_UTF8, 0, dst, -1, textW, count);
936             GlobalUnlock(unicode_handle);
937         }
938
939         HeapFree(GetProcessHeap(), 0, dst);
940     }
941
942     return unicode_handle;
943 }
944
945
946 /**************************************************************************
947  *              export_clipboard_data
948  *
949  *  Generic export clipboard data routine.
950  */
951 static CFDataRef export_clipboard_data(HANDLE data)
952 {
953     CFDataRef ret;
954     UINT len;
955     LPVOID src;
956
957     len = GlobalSize(data);
958     src = GlobalLock(data);
959     if (!src) return NULL;
960
961     ret = CFDataCreate(NULL, src, len);
962     GlobalUnlock(data);
963
964     return ret;
965 }
966
967
968 /**************************************************************************
969  *              export_bitmap_to_bmp
970  *
971  *  Export CF_BITMAP to BMP file format.
972  */
973 static CFDataRef export_bitmap_to_bmp(HANDLE data)
974 {
975     CFDataRef ret = NULL;
976     HGLOBAL dib;
977
978     dib = create_dib_from_bitmap(data);
979     if (dib)
980     {
981         ret = export_dib_to_bmp(dib);
982         GlobalFree(dib);
983     }
984
985     return ret;
986 }
987
988
989 /**************************************************************************
990  *              export_codepage_to_utf8
991  *
992  *  Export string data in a specified codepage to UTF-8.
993  */
994 static CFDataRef export_codepage_to_utf8(HANDLE data, UINT cp)
995 {
996     CFDataRef ret = NULL;
997     const char* str;
998
999     if ((str = GlobalLock(data)))
1000     {
1001         HANDLE unicode = convert_text(str, GlobalSize(data), cp, -1);
1002
1003         ret = export_unicodetext_to_utf8(unicode);
1004
1005         GlobalFree(unicode);
1006         GlobalUnlock(data);
1007     }
1008
1009     return ret;
1010 }
1011
1012
1013 /**************************************************************************
1014  *              export_dib_to_bmp
1015  *
1016  *  Export CF_DIB to BMP file format.  This just entails prepending a BMP
1017  *  file format header to the data.
1018  */
1019 static CFDataRef export_dib_to_bmp(HANDLE data)
1020 {
1021     CFMutableDataRef ret = NULL;
1022     BYTE *dibdata;
1023     CFIndex len;
1024     BITMAPFILEHEADER bfh;
1025
1026     dibdata = GlobalLock(data);
1027     if (!dibdata)
1028         return NULL;
1029
1030     len = sizeof(bfh) + GlobalSize(data);
1031     ret = CFDataCreateMutable(NULL, len);
1032     if (ret)
1033     {
1034         bfh.bfType = 0x4d42; /* "BM" */
1035         bfh.bfSize = len;
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));
1040
1041         /* rest of bitmap is the same as the packed dib */
1042         CFDataAppendBytes(ret, (UInt8*)dibdata, len - sizeof(bfh));
1043     }
1044
1045     GlobalUnlock(data);
1046
1047     return ret;
1048 }
1049
1050
1051 /**************************************************************************
1052  *              export_hdrop_to_filenames
1053  *
1054  *  Export CF_HDROP to NSFilenamesPboardType data, which is a CFArray of
1055  *  CFStrings (holding Unix paths) which is serialized as a property list.
1056  */
1057 static CFDataRef export_hdrop_to_filenames(HANDLE data)
1058 {
1059     CFDataRef ret = NULL;
1060     DROPFILES *dropfiles;
1061     CFMutableArrayRef filenames = NULL;
1062     void *p;
1063     WCHAR *buffer = NULL;
1064     size_t buffer_len = 0;
1065
1066     TRACE("data %p\n", data);
1067
1068     if (!(dropfiles = GlobalLock(data)))
1069     {
1070         WARN("failed to lock data %p\n", data);
1071         goto done;
1072     }
1073
1074     filenames = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1075     if (!filenames)
1076     {
1077         WARN("failed to create filenames array\n");
1078         goto done;
1079     }
1080
1081     p = (char*)dropfiles + dropfiles->pFiles;
1082     while (dropfiles->fWide ? *(WCHAR*)p : *(char*)p)
1083     {
1084         char *unixname;
1085         CFStringRef filename;
1086
1087         TRACE("    %s\n", dropfiles->fWide ? debugstr_w(p) : debugstr_a(p));
1088
1089         if (dropfiles->fWide)
1090             unixname = wine_get_unix_file_name(p);
1091         else
1092         {
1093             int len = MultiByteToWideChar(CP_ACP, 0, p, -1, NULL, 0);
1094             if (len)
1095             {
1096                 if (len > buffer_len)
1097                 {
1098                     HeapFree(GetProcessHeap(), 0, buffer);
1099                     buffer_len = len * 2;
1100                     buffer = HeapAlloc(GetProcessHeap(), 0, buffer_len * sizeof(*buffer));
1101                 }
1102
1103                 MultiByteToWideChar(CP_ACP, 0, p, -1, buffer, buffer_len);
1104                 unixname = wine_get_unix_file_name(buffer);
1105             }
1106             else
1107                 unixname = NULL;
1108         }
1109         if (!unixname)
1110         {
1111             WARN("failed to convert DOS path to Unix: %s\n",
1112                  dropfiles->fWide ? debugstr_w(p) : debugstr_a(p));
1113             goto done;
1114         }
1115
1116         if (dropfiles->fWide)
1117             p = (WCHAR*)p + strlenW(p) + 1;
1118         else
1119             p = (char*)p + strlen(p) + 1;
1120
1121         filename = CFStringCreateWithFileSystemRepresentation(NULL, unixname);
1122         HeapFree(GetProcessHeap(), 0, unixname);
1123         if (!filename)
1124         {
1125             WARN("failed to create CFString from Unix path %s\n", debugstr_a(unixname));
1126             goto done;
1127         }
1128
1129         CFArrayAppendValue(filenames, filename);
1130         CFRelease(filename);
1131     }
1132
1133     ret = CFPropertyListCreateData(NULL, filenames, kCFPropertyListXMLFormat_v1_0, 0, NULL);
1134
1135 done:
1136     HeapFree(GetProcessHeap(), 0, buffer);
1137     GlobalUnlock(data);
1138     if (filenames) CFRelease(filenames);
1139     TRACE(" -> %s\n", debugstr_cf(ret));
1140     return ret;
1141 }
1142
1143
1144 /**************************************************************************
1145  *              export_oemtext_to_utf8
1146  *
1147  *  Export CF_OEMTEXT to UTF-8.
1148  */
1149 static CFDataRef export_oemtext_to_utf8(HANDLE data)
1150 {
1151     return export_codepage_to_utf8(data, CP_OEMCP);
1152 }
1153
1154
1155 /**************************************************************************
1156  *              export_text_to_utf8
1157  *
1158  *  Export CF_TEXT to UTF-8.
1159  */
1160 static CFDataRef export_text_to_utf8(HANDLE data)
1161 {
1162     return export_codepage_to_utf8(data, CP_ACP);
1163 }
1164
1165
1166 /**************************************************************************
1167  *              export_unicodetext_to_utf8
1168  *
1169  *  Export CF_UNICODETEXT to UTF-8.
1170  */
1171 static CFDataRef export_unicodetext_to_utf8(HANDLE data)
1172 {
1173     CFMutableDataRef ret;
1174     LPVOID src;
1175     INT dst_len;
1176
1177     src = GlobalLock(data);
1178     if (!src) return NULL;
1179
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);
1183     if (ret)
1184     {
1185         LPSTR dst;
1186         int i, j;
1187
1188         CFDataSetLength(ret, dst_len);
1189         dst = (LPSTR)CFDataGetMutableBytePtr(ret);
1190         WideCharToMultiByte(CP_UTF8, 0, src, -1, dst, dst_len, NULL, NULL);
1191
1192         /* Remove carriage returns */
1193         for (i = 0, j = 0; i < dst_len; i++)
1194         {
1195             if (dst[i] == '\r' &&
1196                 (i + 1 >= dst_len || dst[i + 1] == '\n' || dst[i + 1] == '\0'))
1197                 continue;
1198             dst[j++] = dst[i];
1199         }
1200         CFDataSetLength(ret, j);
1201     }
1202     GlobalUnlock(data);
1203
1204     return ret;
1205 }
1206
1207
1208 /**************************************************************************
1209  *              get_clipboard_info
1210  */
1211 static BOOL get_clipboard_info(LPCLIPBOARDINFO cbinfo)
1212 {
1213     BOOL ret = FALSE;
1214
1215     SERVER_START_REQ(set_clipboard_info)
1216     {
1217         req->flags = 0;
1218
1219         if (wine_server_call_err(req))
1220         {
1221             ERR("Failed to get clipboard owner.\n");
1222         }
1223         else
1224         {
1225             cbinfo->hwnd_owner = wine_server_ptr_handle(reply->old_owner);
1226             cbinfo->flags = reply->flags;
1227
1228             ret = TRUE;
1229         }
1230     }
1231     SERVER_END_REQ;
1232
1233     return ret;
1234 }
1235
1236
1237 /**************************************************************************
1238  *              release_ownership
1239  */
1240 static BOOL release_ownership(void)
1241 {
1242     BOOL ret = FALSE;
1243
1244     SERVER_START_REQ(set_clipboard_info)
1245     {
1246         req->flags = SET_CB_RELOWNER | SET_CB_SEQNO;
1247
1248         if (wine_server_call_err(req))
1249             ERR("Failed to set clipboard.\n");
1250         else
1251             ret = TRUE;
1252     }
1253     SERVER_END_REQ;
1254
1255     return ret;
1256 }
1257
1258
1259 /**************************************************************************
1260  *              macdrv_get_pasteboard_data
1261  */
1262 HANDLE macdrv_get_pasteboard_data(CFTypeRef pasteboard, UINT desired_format)
1263 {
1264     CFArrayRef types;
1265     CFIndex count;
1266     CFIndex i;
1267     CFStringRef type, best_type;
1268     WINE_CLIPFORMAT* best_format = NULL;
1269     HANDLE data = NULL;
1270
1271     TRACE("pasteboard %p, desired_format %s\n", pasteboard, debugstr_format(desired_format));
1272
1273     types = macdrv_copy_pasteboard_types(pasteboard);
1274     if (!types)
1275     {
1276         WARN("Failed to copy pasteboard types\n");
1277         return NULL;
1278     }
1279
1280     count = CFArrayGetCount(types);
1281     TRACE("got %ld types\n", count);
1282
1283     for (i = 0; (!best_format || best_format->synthesized) && i < count; i++)
1284     {
1285         WINE_CLIPFORMAT* format;
1286
1287         type = CFArrayGetValueAtIndex(types, i);
1288
1289         format = NULL;
1290         while ((!best_format || best_format->synthesized) && (format = format_for_type(format, type)))
1291         {
1292             TRACE("for type %s got format %p/%s\n", debugstr_cf(type), format, debugstr_format(format ? format->format_id : 0));
1293
1294             if (format->format_id == desired_format)
1295             {
1296                 /* The best format is the matching one which is not synthesized.  Failing that,
1297                    the best format is the first matching synthesized format. */
1298                 if (!format->synthesized || !best_format)
1299                 {
1300                     best_type = type;
1301                     best_format = format;
1302                 }
1303             }
1304         }
1305     }
1306
1307     if (best_format)
1308     {
1309         CFDataRef pasteboard_data = macdrv_copy_pasteboard_data(pasteboard, best_type);
1310
1311         TRACE("got pasteboard data for type %s: %s\n", debugstr_cf(best_type), debugstr_cf(pasteboard_data));
1312
1313         if (pasteboard_data)
1314         {
1315             data = best_format->import_func(pasteboard_data);
1316             CFRelease(pasteboard_data);
1317         }
1318     }
1319
1320     CFRelease(types);
1321     TRACE(" -> %p\n", data);
1322     return data;
1323 }
1324
1325
1326 /**************************************************************************
1327  *              macdrv_pasteboard_has_format
1328  */
1329 BOOL macdrv_pasteboard_has_format(CFTypeRef pasteboard, UINT desired_format)
1330 {
1331     CFArrayRef types;
1332     int count;
1333     UINT i;
1334     BOOL found = FALSE;
1335
1336     TRACE("pasteboard %p, desired_format %s\n", pasteboard, debugstr_format(desired_format));
1337
1338     types = macdrv_copy_pasteboard_types(pasteboard);
1339     if (!types)
1340     {
1341         WARN("Failed to copy pasteboard types\n");
1342         return FALSE;
1343     }
1344
1345     count = CFArrayGetCount(types);
1346     TRACE("got %d types\n", count);
1347
1348     for (i = 0; !found && i < count; i++)
1349     {
1350         CFStringRef type = CFArrayGetValueAtIndex(types, i);
1351         WINE_CLIPFORMAT* format;
1352
1353         format = NULL;
1354         while (!found && (format = format_for_type(format, type)))
1355         {
1356             TRACE("for type %s got format %s\n", debugstr_cf(type), debugstr_format(format->format_id));
1357
1358             if (format->format_id == desired_format)
1359                 found = TRUE;
1360         }
1361     }
1362
1363     CFRelease(types);
1364     TRACE(" -> %d\n", found);
1365     return found;
1366 }
1367
1368
1369 /**************************************************************************
1370  *              macdrv_copy_pasteboard_formats
1371  */
1372 CFArrayRef macdrv_copy_pasteboard_formats(CFTypeRef pasteboard)
1373 {
1374     CFArrayRef types;
1375     CFIndex count;
1376     CFMutableArrayRef formats;
1377     CFIndex i;
1378
1379     TRACE("pasteboard %p\n", pasteboard);
1380
1381     types = macdrv_copy_pasteboard_types(pasteboard);
1382     if (!types)
1383     {
1384         WARN("Failed to copy pasteboard types\n");
1385         return NULL;
1386     }
1387
1388     count = CFArrayGetCount(types);
1389     TRACE("got %ld types\n", count);
1390
1391     if (!count)
1392     {
1393         CFRelease(types);
1394         return NULL;
1395     }
1396
1397     formats = CFArrayCreateMutable(NULL, 0, NULL);
1398     if (!formats)
1399     {
1400         WARN("Failed to allocate formats array\n");
1401         CFRelease(types);
1402         return NULL;
1403     }
1404
1405     for (i = 0; i < count; i++)
1406     {
1407         CFStringRef type = CFArrayGetValueAtIndex(types, i);
1408         WINE_CLIPFORMAT* format;
1409
1410         format = NULL;
1411         while ((format = format_for_type(format, type)))
1412         {
1413             TRACE("for type %s got format %p/%s\n", debugstr_cf(type), format, debugstr_format(format->format_id));
1414
1415             if (format->synthesized)
1416             {
1417                 /* Don't override a real value with a synthesized value. */
1418                 if (!CFArrayContainsValue(formats, CFRangeMake(0, CFArrayGetCount(formats)), (void*)format->format_id))
1419                     CFArrayAppendValue(formats, (void*)format->format_id);
1420             }
1421             else
1422             {
1423                 /* If the type was already in the array, it must have been synthesized
1424                    because this one's real.  Remove the synthesized entry in favor of
1425                    this one. */
1426                 CFIndex index = CFArrayGetFirstIndexOfValue(formats, CFRangeMake(0, CFArrayGetCount(formats)),
1427                                                             (void*)format->format_id);
1428                 if (index != kCFNotFound)
1429                     CFArrayRemoveValueAtIndex(formats, index);
1430                 CFArrayAppendValue(formats, (void*)format->format_id);
1431             }
1432         }
1433     }
1434
1435     CFRelease(types);
1436
1437     TRACE(" -> %s\n", debugstr_cf(formats));
1438     return formats;
1439 }
1440
1441
1442 /**************************************************************************
1443  *              check_clipboard_ownership
1444  */
1445 static void check_clipboard_ownership(HWND *owner)
1446 {
1447     CLIPBOARDINFO cbinfo;
1448
1449     if (owner) *owner = NULL;
1450
1451     /* If Wine thinks we're the clipboard owner but Mac OS X thinks we're not
1452        the pasteboard owner, update Wine. */
1453     if (get_clipboard_info(&cbinfo) && (cbinfo.flags & CB_PROCESS))
1454     {
1455         if (!(cbinfo.flags & CB_OPEN) && !macdrv_is_pasteboard_owner())
1456         {
1457             TRACE("Lost clipboard ownership\n");
1458
1459             if (OpenClipboard(cbinfo.hwnd_owner))
1460             {
1461                 /* Destroy private objects */
1462                 SendMessageW(cbinfo.hwnd_owner, WM_DESTROYCLIPBOARD, 0, 0);
1463
1464                 /* Give up ownership of the windows clipboard */
1465                 release_ownership();
1466                 CloseClipboard();
1467             }
1468         }
1469         else if (owner)
1470             *owner = cbinfo.hwnd_owner;
1471     }
1472 }
1473
1474
1475 /**************************************************************************
1476  *              Mac User Driver Clipboard Exports
1477  **************************************************************************/
1478
1479
1480 /**************************************************************************
1481  *              AcquireClipboard (MACDRV.@)
1482  */
1483 int CDECL macdrv_AcquireClipboard(HWND hwnd)
1484 {
1485     TRACE("hwnd %p\n", hwnd);
1486     check_clipboard_ownership(NULL);
1487     return 0;
1488 }
1489
1490
1491 /**************************************************************************
1492  *              CountClipboardFormats (MACDRV.@)
1493  */
1494 INT CDECL macdrv_CountClipboardFormats(void)
1495 {
1496     CFMutableSetRef seen_formats;
1497     CFArrayRef types;
1498     CFIndex count;
1499     CFIndex i;
1500     INT ret = 0;
1501
1502     TRACE("()\n");
1503     check_clipboard_ownership(NULL);
1504
1505     seen_formats = CFSetCreateMutable(NULL, 0, NULL);
1506     if (!seen_formats)
1507     {
1508         WARN("Failed to allocate set to track seen formats\n");
1509         return 0;
1510     }
1511
1512     types = macdrv_copy_pasteboard_types(NULL);
1513     if (!types)
1514     {
1515         WARN("Failed to copy pasteboard types\n");
1516         CFRelease(seen_formats);
1517         return 0;
1518     }
1519
1520     count = CFArrayGetCount(types);
1521     TRACE("got %ld types\n", count);
1522
1523     for (i = 0; i < count; i++)
1524     {
1525         CFStringRef type = CFArrayGetValueAtIndex(types, i);
1526         WINE_CLIPFORMAT* format;
1527
1528         format = NULL;
1529         while ((format = format_for_type(format, type)))
1530         {
1531             TRACE("for type %s got format %p/%s\n", debugstr_cf(type), format, debugstr_format(format->format_id));
1532
1533             if (!CFSetContainsValue(seen_formats, (void*)format->format_id))
1534             {
1535                 ret++;
1536                 CFSetAddValue(seen_formats, (void*)format->format_id);
1537             }
1538         }
1539     }
1540
1541     CFRelease(seen_formats);
1542     TRACE(" -> %d\n", ret);
1543     return ret;
1544 }
1545
1546
1547 /**************************************************************************
1548  *              EmptyClipboard (MACDRV.@)
1549  *
1550  * Empty cached clipboard data.
1551  */
1552 void CDECL macdrv_EmptyClipboard(BOOL keepunowned)
1553 {
1554     TRACE("keepunowned %d\n", keepunowned);
1555     macdrv_clear_pasteboard();
1556 }
1557
1558
1559 /**************************************************************************
1560  *              EndClipboardUpdate (MACDRV.@)
1561  */
1562 void CDECL macdrv_EndClipboardUpdate(void)
1563 {
1564     TRACE("()\n");
1565     check_clipboard_ownership(NULL);
1566 }
1567
1568
1569 /**************************************************************************
1570  *              EnumClipboardFormats (MACDRV.@)
1571  */
1572 UINT CDECL macdrv_EnumClipboardFormats(UINT prev_format)
1573 {
1574     CFIndex count;
1575     CFIndex i;
1576     UINT ret = 0;
1577
1578     TRACE("prev_format %s\n", debugstr_format(prev_format));
1579     check_clipboard_ownership(NULL);
1580
1581     if (prev_format)
1582     {
1583         CFArrayRef formats = macdrv_copy_pasteboard_formats(NULL);
1584         if (formats)
1585         {
1586             count = CFArrayGetCount(formats);
1587             i = CFArrayGetFirstIndexOfValue(formats, CFRangeMake(0, count), (void*)prev_format);
1588             if (i != kCFNotFound && i + 1 < count)
1589                 ret = (UINT)CFArrayGetValueAtIndex(formats, i + 1);
1590
1591             CFRelease(formats);
1592         }
1593     }
1594     else
1595     {
1596         CFArrayRef types = macdrv_copy_pasteboard_types(NULL);
1597         if (types)
1598         {
1599             count = CFArrayGetCount(types);
1600             TRACE("got %ld types\n", count);
1601
1602             if (count)
1603             {
1604                 CFStringRef type = CFArrayGetValueAtIndex(types, 0);
1605                 WINE_CLIPFORMAT *format = format_for_type(NULL, type);
1606
1607                 ret = format ? format->format_id : 0;
1608             }
1609
1610             CFRelease(types);
1611         }
1612         else
1613             WARN("Failed to copy pasteboard types\n");
1614     }
1615
1616     TRACE(" -> %u\n", ret);
1617     return ret;
1618 }
1619
1620
1621 /**************************************************************************
1622  *              GetClipboardData (MACDRV.@)
1623  */
1624 HANDLE CDECL macdrv_GetClipboardData(UINT desired_format)
1625 {
1626     check_clipboard_ownership(NULL);
1627
1628     return macdrv_get_pasteboard_data(NULL, desired_format);
1629 }
1630
1631
1632 /**************************************************************************
1633  *              IsClipboardFormatAvailable (MACDRV.@)
1634  */
1635 BOOL CDECL macdrv_IsClipboardFormatAvailable(UINT desired_format)
1636 {
1637     check_clipboard_ownership(NULL);
1638     return macdrv_pasteboard_has_format(NULL, desired_format);
1639 }
1640
1641
1642 /**************************************************************************
1643  *              SetClipboardData (MACDRV.@)
1644  */
1645 BOOL CDECL macdrv_SetClipboardData(UINT format_id, HANDLE data, BOOL owner)
1646 {
1647     HWND hwnd_owner;
1648     macdrv_window window;
1649     WINE_CLIPFORMAT *format;
1650     CFDataRef cfdata = NULL;
1651
1652     check_clipboard_ownership(&hwnd_owner);
1653     window = macdrv_get_cocoa_window(GetAncestor(hwnd_owner, GA_ROOT), FALSE);
1654     TRACE("format_id %s data %p owner %d hwnd_owner %p window %p)\n", debugstr_format(format_id), data, owner, hwnd_owner, window);
1655
1656     /* Find the "natural" format for this format_id (the one which isn't
1657        synthesized from another type). */
1658     LIST_FOR_EACH_ENTRY(format, &format_list, WINE_CLIPFORMAT, entry)
1659         if (format->format_id == format_id && !format->synthesized) break;
1660
1661     if (&format->entry == &format_list && !(format = insert_clipboard_format(format_id, NULL)))
1662     {
1663         WARN("Failed to register clipboard format %s\n", debugstr_format(format_id));
1664         return FALSE;
1665     }
1666
1667     /* Export the data to the Mac pasteboard. */
1668     if (data)
1669     {
1670         if (!format->export_func || !(cfdata = format->export_func(data)))
1671         {
1672             WARN("Failed to export %s data to type %s\n", debugstr_format(format_id), debugstr_cf(format->type));
1673             return FALSE;
1674         }
1675     }
1676
1677     if (macdrv_set_pasteboard_data(format->type, cfdata, window))
1678         TRACE("Set pasteboard data for type %s: %s\n", debugstr_cf(format->type), debugstr_cf(cfdata));
1679     else
1680     {
1681         WARN("Failed to set pasteboard data for type %s: %s\n", debugstr_cf(format->type), debugstr_cf(cfdata));
1682         if (cfdata) CFRelease(cfdata);
1683         return FALSE;
1684     }
1685
1686     if (cfdata) CFRelease(cfdata);
1687
1688     /* Find any other formats for this format_id (the exportable synthesized ones). */
1689     LIST_FOR_EACH_ENTRY(format, &format_list, WINE_CLIPFORMAT, entry)
1690     {
1691         if (format->format_id == format_id && format->synthesized && format->export_func)
1692         {
1693             /* We have a synthesized format for this format ID.  Add its type to the pasteboard. */
1694             TRACE("Synthesized from format %s: type %s\n", debugstr_format(format_id), debugstr_cf(format->type));
1695
1696             if (data)
1697             {
1698                 cfdata = format->export_func(data);
1699                 if (!cfdata)
1700                 {
1701                     WARN("Failed to export %s data to type %s\n", debugstr_format(format->format_id), debugstr_cf(format->type));
1702                     continue;
1703                 }
1704             }
1705             else
1706                 cfdata = NULL;
1707
1708             if (macdrv_set_pasteboard_data(format->type, cfdata, window))
1709                 TRACE("    ... set pasteboard data: %s\n", debugstr_cf(cfdata));
1710             else
1711                 WARN("    ... failed to set pasteboard data: %s\n", debugstr_cf(cfdata));
1712
1713             if (cfdata) CFRelease(cfdata);
1714         }
1715     }
1716
1717     if (data)
1718     {
1719         /* FIXME: According to MSDN, the caller is entitled to lock and read from
1720            data until CloseClipboard is called.  So, we should defer this cleanup. */
1721         if ((format_id >= CF_GDIOBJFIRST && format_id <= CF_GDIOBJLAST) ||
1722             format_id == CF_BITMAP ||
1723             format_id == CF_DIB ||
1724             format_id == CF_PALETTE)
1725         {
1726             DeleteObject(data);
1727         }
1728         else if (format_id == CF_METAFILEPICT)
1729         {
1730             DeleteMetaFile(((METAFILEPICT *)GlobalLock(data))->hMF);
1731             GlobalFree(data);
1732         }
1733         else if (format_id == CF_ENHMETAFILE)
1734         {
1735             DeleteEnhMetaFile(data);
1736         }
1737         else if (format_id < CF_PRIVATEFIRST || CF_PRIVATELAST < format_id)
1738         {
1739             GlobalFree(data);
1740         }
1741     }
1742
1743     return TRUE;
1744 }
1745
1746
1747 /**************************************************************************
1748  *              MACDRV Private Clipboard Exports
1749  **************************************************************************/
1750
1751
1752 /**************************************************************************
1753  *              macdrv_clipboard_process_attach
1754  */
1755 void macdrv_clipboard_process_attach(void)
1756 {
1757     UINT i;
1758
1759     /* Register built-in formats */
1760     for (i = 0; i < sizeof(builtin_format_ids)/sizeof(builtin_format_ids[0]); i++)
1761     {
1762         WINE_CLIPFORMAT *format;
1763
1764         if (!(format = HeapAlloc(GetProcessHeap(), 0, sizeof(*format)))) break;
1765         format->format_id   = builtin_format_ids[i].id;
1766         format->type        = CFRetain(builtin_format_ids[i].type);
1767         format->import_func = builtin_format_ids[i].import;
1768         format->export_func = builtin_format_ids[i].export;
1769         format->synthesized = builtin_format_ids[i].synthesized;
1770         list_add_tail(&format_list, &format->entry);
1771     }
1772
1773     /* Register known mappings between Windows formats and Mac types */
1774     for (i = 0; i < sizeof(builtin_format_names)/sizeof(builtin_format_names[0]); i++)
1775         insert_clipboard_format(RegisterClipboardFormatW(builtin_format_names[i].name),
1776                                 builtin_format_names[i].type);
1777 }
1778
1779
1780 /**************************************************************************
1781  *              query_pasteboard_data
1782  */
1783 BOOL query_pasteboard_data(HWND hwnd, CFStringRef type)
1784 {
1785     BOOL ret = FALSE;
1786     CLIPBOARDINFO cbinfo;
1787     WINE_CLIPFORMAT* format;
1788     CFArrayRef types = NULL;
1789     CFRange range;
1790
1791     TRACE("hwnd %p type %s\n", hwnd, debugstr_cf(type));
1792
1793     if (get_clipboard_info(&cbinfo))
1794         hwnd = cbinfo.hwnd_owner;
1795
1796     format = NULL;
1797     while ((format = format_for_type(format, type)))
1798     {
1799         WINE_CLIPFORMAT* base_format;
1800
1801         TRACE("for type %s got format %p/%s\n", debugstr_cf(type), format, debugstr_format(format->format_id));
1802
1803         if (!format->synthesized)
1804         {
1805             TRACE("Sending WM_RENDERFORMAT message for format %s to hwnd %p\n", debugstr_format(format->format_id), hwnd);
1806             SendMessageW(hwnd, WM_RENDERFORMAT, format->format_id, 0);
1807             ret = TRUE;
1808             goto done;
1809         }
1810
1811         if (!types)
1812         {
1813             types = macdrv_copy_pasteboard_types(NULL);
1814             if (!types)
1815             {
1816                 WARN("Failed to copy pasteboard types\n");
1817                 break;
1818             }
1819
1820             range = CFRangeMake(0, CFArrayGetCount(types));
1821         }
1822
1823         /* The type maps to a synthesized format.  Now look up what type that format maps to natively
1824            (not synthesized).  For example, if type is "public.utf8-plain-text", then this format may
1825            have an ID of CF_TEXT.  From CF_TEXT, we want to find "org.winehq.builtin.text" to see if
1826            that type is present in the pasteboard.  If it is, then the app must have promised it and
1827            we can ask it to render it.  (If it had put it on the clipboard immediately, then the
1828            pasteboard would also have data for "public.utf8-plain-text" and we wouldn't be here.)  If
1829            "org.winehq.builtin.text" is not on the pasteboard, then one of the other text formats is
1830            presumably responsible for the promise that we're trying to satisfy, so we keep looking. */
1831         LIST_FOR_EACH_ENTRY(base_format, &format_list, WINE_CLIPFORMAT, entry)
1832         {
1833             if (base_format->format_id == format->format_id && !base_format->synthesized &&
1834                 CFArrayContainsValue(types, range, base_format->type))
1835             {
1836                 TRACE("Sending WM_RENDERFORMAT message for format %s to hwnd %p\n", debugstr_format(base_format->format_id), hwnd);
1837                 SendMessageW(hwnd, WM_RENDERFORMAT, base_format->format_id, 0);
1838                 ret = TRUE;
1839                 goto done;
1840             }
1841         }
1842     }
1843
1844 done:
1845     if (types) CFRelease(types);
1846
1847     return ret;
1848 }