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