4 * Copyright 1994 Martin Ayotte
7 * 2003 Ulrich Czekalla for CodeWeavers
8 * Copyright 2011, 2012, 2013 Ken Thomases for CodeWeavers Inc.
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
31 #include "wine/list.h"
32 #include "wine/server.h"
33 #include "wine/unicode.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(clipboard
);
39 /**************************************************************************
41 **************************************************************************/
47 } CLIPBOARDINFO
, *LPCLIPBOARDINFO
;
49 typedef HANDLE (*DRVIMPORTFUNC
)(CFDataRef data
);
50 typedef CFDataRef (*DRVEXPORTFUNC
)(HANDLE data
);
57 DRVIMPORTFUNC import_func
;
58 DRVEXPORTFUNC export_func
;
63 /**************************************************************************
65 **************************************************************************/
68 /**************************************************************************
69 * Forward Function Declarations
70 **************************************************************************/
72 static HANDLE
import_clipboard_data(CFDataRef data
);
73 static HANDLE
import_bmp_to_bitmap(CFDataRef data
);
74 static HANDLE
import_bmp_to_dib(CFDataRef data
);
75 static HANDLE
import_nsfilenames_to_hdrop(CFDataRef data
);
76 static HANDLE
import_oemtext_to_text(CFDataRef data
);
77 static HANDLE
import_oemtext_to_unicodetext(CFDataRef data
);
78 static HANDLE
import_text_to_oemtext(CFDataRef data
);
79 static HANDLE
import_text_to_unicodetext(CFDataRef data
);
80 static HANDLE
import_unicodetext_to_oemtext(CFDataRef data
);
81 static HANDLE
import_unicodetext_to_text(CFDataRef data
);
82 static HANDLE
import_utf8_to_oemtext(CFDataRef data
);
83 static HANDLE
import_utf8_to_text(CFDataRef data
);
84 static HANDLE
import_utf8_to_unicodetext(CFDataRef data
);
86 static CFDataRef
export_clipboard_data(HANDLE data
);
87 static CFDataRef
export_bitmap_to_bmp(HANDLE data
);
88 static CFDataRef
export_dib_to_bmp(HANDLE data
);
89 static CFDataRef
export_hdrop_to_filenames(HANDLE data
);
90 static CFDataRef
export_oemtext_to_utf8(HANDLE data
);
91 static CFDataRef
export_text_to_utf8(HANDLE data
);
92 static CFDataRef
export_unicodetext_to_utf8(HANDLE data
);
95 /**************************************************************************
97 **************************************************************************/
99 /* Clipboard formats */
100 static struct list format_list
= LIST_INIT(format_list
);
102 /* There are two naming schemes involved and we want to have a mapping between
103 them. There are Win32 clipboard format names and there are Mac pasteboard
106 The Win32 standard clipboard formats don't have names, but they are associated
107 with Mac pasteboard types through the following tables, which are used to
108 initialize the format_list. Where possible, the standard clipboard formats
109 are mapped to predefined pasteboard type UTIs. Otherwise, we create Wine-
110 specific types of the form "org.winehq.builtin.<format>", where <format> is
111 the name of the symbolic constant for the format minus "CF_" and lowercased.
112 E.g. CF_BITMAP -> org.winehq.builtin.bitmap.
114 Win32 clipboard formats which originate in a Windows program may be registered
115 with an arbitrary name. We construct a Mac pasteboard type from these by
116 prepending "org.winehq.registered." to the registered name.
118 Likewise, Mac pasteboard types which originate in other apps may have
119 arbitrary type strings. We construct a Win32 clipboard format name from
120 these by prepending "org.winehq.mac-type." to the Mac pasteboard type.
123 Win32 clipboard format names:
124 <none> standard clipboard format; maps via
125 format_list to either a predefined Mac UTI
126 or org.winehq.builtin.<format>.
127 org.winehq.mac-type.<Mac type> representation of Mac type in Win32 land;
129 <other> name registered within Win32 land; maps to
130 org.winehq.registered.<other>
131 Mac pasteboard type names:
132 org.winehq.builtin.<format ID> representation of Win32 standard clipboard
133 format for which there was no corresponding
134 predefined Mac UTI; maps via format_list
135 org.winehq.registered.<format name> representation of Win32 registered
136 clipboard format name; maps to <format name>
137 <other> Mac pasteboard type originating with system
138 or other apps; either maps via format_list
139 to a standard clipboard format or maps to
140 org.winehq.mac-type.<other>
147 DRVIMPORTFUNC import
;
148 DRVEXPORTFUNC export
;
150 } builtin_format_ids
[] =
152 { CF_DIBV5
, CFSTR("org.winehq.builtin.dibv5"), import_clipboard_data
, export_clipboard_data
, FALSE
},
153 { CF_DIF
, CFSTR("org.winehq.builtin.dif"), import_clipboard_data
, export_clipboard_data
, FALSE
},
154 { CF_DSPBITMAP
, CFSTR("org.winehq.builtin.dspbitmap"), import_clipboard_data
, export_clipboard_data
, FALSE
},
155 { CF_DSPENHMETAFILE
, CFSTR("org.winehq.builtin.dspenhmetafile"), import_clipboard_data
, export_clipboard_data
, FALSE
},
156 { CF_DSPMETAFILEPICT
, CFSTR("org.winehq.builtin.dspmetafilepict"), import_clipboard_data
, export_clipboard_data
, FALSE
},
157 { CF_DSPTEXT
, CFSTR("org.winehq.builtin.dsptext"), import_clipboard_data
, export_clipboard_data
, FALSE
},
158 { CF_LOCALE
, CFSTR("org.winehq.builtin.locale"), import_clipboard_data
, export_clipboard_data
, FALSE
},
159 { CF_OWNERDISPLAY
, CFSTR("org.winehq.builtin.ownerdisplay"), import_clipboard_data
, export_clipboard_data
, FALSE
},
160 { CF_PALETTE
, CFSTR("org.winehq.builtin.palette"), import_clipboard_data
, export_clipboard_data
, FALSE
},
161 { CF_PENDATA
, CFSTR("org.winehq.builtin.pendata"), import_clipboard_data
, export_clipboard_data
, FALSE
},
162 { CF_RIFF
, CFSTR("org.winehq.builtin.riff"), import_clipboard_data
, export_clipboard_data
, FALSE
},
163 { CF_SYLK
, CFSTR("org.winehq.builtin.sylk"), import_clipboard_data
, export_clipboard_data
, FALSE
},
164 { CF_TIFF
, CFSTR("public.tiff"), import_clipboard_data
, export_clipboard_data
, FALSE
},
165 { CF_WAVE
, CFSTR("com.microsoft.waveform-audio"), import_clipboard_data
, export_clipboard_data
, FALSE
},
167 { CF_UNICODETEXT
, CFSTR("org.winehq.builtin.unicodetext"), import_clipboard_data
, export_clipboard_data
, FALSE
},
168 { CF_TEXT
, CFSTR("org.winehq.builtin.unicodetext"), import_unicodetext_to_text
, NULL
, TRUE
},
169 { CF_OEMTEXT
, CFSTR("org.winehq.builtin.unicodetext"), import_unicodetext_to_oemtext
, NULL
, TRUE
},
171 { CF_TEXT
, CFSTR("org.winehq.builtin.text"), import_clipboard_data
, export_clipboard_data
, FALSE
},
172 { CF_UNICODETEXT
, CFSTR("org.winehq.builtin.text"), import_text_to_unicodetext
, NULL
, TRUE
},
173 { CF_OEMTEXT
, CFSTR("org.winehq.builtin.text"), import_text_to_oemtext
, NULL
, TRUE
},
175 { CF_OEMTEXT
, CFSTR("org.winehq.builtin.oemtext"), import_clipboard_data
, export_clipboard_data
, FALSE
},
176 { CF_UNICODETEXT
, CFSTR("org.winehq.builtin.oemtext"), import_oemtext_to_unicodetext
, NULL
, TRUE
},
177 { CF_TEXT
, CFSTR("org.winehq.builtin.oemtext"), import_oemtext_to_text
, NULL
, TRUE
},
179 { CF_UNICODETEXT
, CFSTR("public.utf8-plain-text"), import_utf8_to_unicodetext
, export_unicodetext_to_utf8
, TRUE
},
180 { CF_TEXT
, CFSTR("public.utf8-plain-text"), import_utf8_to_text
, export_text_to_utf8
, TRUE
},
181 { CF_OEMTEXT
, CFSTR("public.utf8-plain-text"), import_utf8_to_oemtext
, export_oemtext_to_utf8
, TRUE
},
183 { CF_DIB
, CFSTR("org.winehq.builtin.dib"), import_clipboard_data
, export_clipboard_data
, FALSE
},
184 { CF_DIB
, CFSTR("com.microsoft.bmp"), import_bmp_to_dib
, export_dib_to_bmp
, TRUE
},
186 { CF_BITMAP
, CFSTR("org.winehq.builtin.bitmap"), import_bmp_to_bitmap
, export_bitmap_to_bmp
, FALSE
},
187 { CF_BITMAP
, CFSTR("com.microsoft.bmp"), import_bmp_to_bitmap
, export_bitmap_to_bmp
, TRUE
},
189 { CF_HDROP
, CFSTR("org.winehq.builtin.hdrop"), import_clipboard_data
, export_clipboard_data
, FALSE
},
190 { CF_HDROP
, CFSTR("NSFilenamesPboardType"), import_nsfilenames_to_hdrop
, export_hdrop_to_filenames
, TRUE
},
193 static const WCHAR wszRichTextFormat
[] = {'R','i','c','h',' ','T','e','x','t',' ','F','o','r','m','a','t',0};
194 static const WCHAR wszGIF
[] = {'G','I','F',0};
195 static const WCHAR wszJFIF
[] = {'J','F','I','F',0};
196 static const WCHAR wszPNG
[] = {'P','N','G',0};
197 static const WCHAR wszHTMLFormat
[] = {'H','T','M','L',' ','F','o','r','m','a','t',0};
202 DRVIMPORTFUNC import
;
203 DRVEXPORTFUNC export
;
204 } builtin_format_names
[] =
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
},
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};
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.");
221 /**************************************************************************
222 * Internal Clipboard implementation methods
223 **************************************************************************/
226 * format_list functions
229 /**************************************************************************
232 const char *debugstr_format(UINT id
)
236 if (GetClipboardFormatNameW(id
, buffer
, 256))
237 return wine_dbg_sprintf("0x%04x %s", id
, debugstr_w(buffer
));
241 #define BUILTIN(id) case id: return #id;
244 BUILTIN(CF_METAFILEPICT
)
254 BUILTIN(CF_UNICODETEXT
)
255 BUILTIN(CF_ENHMETAFILE
)
259 BUILTIN(CF_OWNERDISPLAY
)
261 BUILTIN(CF_DSPBITMAP
)
262 BUILTIN(CF_DSPMETAFILEPICT
)
263 BUILTIN(CF_DSPENHMETAFILE
)
265 default: return wine_dbg_sprintf("0x%04x", id
);
270 /**************************************************************************
271 * insert_clipboard_format
273 static WINE_CLIPFORMAT
*insert_clipboard_format(UINT id
, CFStringRef type
)
275 WINE_CLIPFORMAT
*format
;
277 format
= HeapAlloc(GetProcessHeap(), 0, sizeof(*format
));
281 WARN("No more memory for a new format!\n");
284 format
->format_id
= id
;
285 format
->import_func
= import_clipboard_data
;
286 format
->export_func
= export_clipboard_data
;
287 format
->synthesized
= FALSE
;
290 format
->type
= CFStringCreateCopy(NULL
, type
);
295 if (!GetClipboardFormatNameW(format
->format_id
, buffer
, sizeof(buffer
) / sizeof(buffer
[0])))
297 WARN("failed to get name for format %s; error 0x%08x\n", debugstr_format(format
->format_id
), GetLastError());
298 HeapFree(GetProcessHeap(), 0, format
);
302 if (!strncmpW(buffer
, mac_type_name_prefix
, strlenW(mac_type_name_prefix
)))
304 const WCHAR
*p
= buffer
+ strlenW(mac_type_name_prefix
);
305 format
->type
= CFStringCreateWithCharacters(NULL
, (UniChar
*)p
, strlenW(p
));
309 format
->type
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@%S"),
310 registered_name_type_prefix
, buffer
);
314 list_add_tail(&format_list
, &format
->entry
);
316 TRACE("Registering format %s type %s\n", debugstr_format(format
->format_id
),
317 debugstr_cf(format
->type
));
323 /**************************************************************************
326 * Register a custom Mac clipboard format.
328 static WINE_CLIPFORMAT
* register_format(UINT id
, CFStringRef type
)
330 WINE_CLIPFORMAT
*format
;
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
;
336 return insert_clipboard_format(id
, type
);
340 /**************************************************************************
343 static WINE_CLIPFORMAT
* format_for_type(WINE_CLIPFORMAT
*current
, CFStringRef type
)
345 struct list
*ptr
= current
? ¤t
->entry
: &format_list
;
346 WINE_CLIPFORMAT
*format
= NULL
;
348 TRACE("current %p/%s type %s\n", current
, debugstr_format(current
? current
->format_id
: 0), debugstr_cf(type
));
350 while ((ptr
= list_next(&format_list
, ptr
)))
352 format
= LIST_ENTRY(ptr
, WINE_CLIPFORMAT
, entry
);
353 if (CFEqual(format
->type
, type
))
355 TRACE(" -> %p/%s\n", format
, debugstr_format(format
->format_id
));
364 if (CFStringHasPrefix(type
, CFSTR("org.winehq.builtin.")))
366 ERR("Shouldn't happen. Built-in type %s should have matched something in format list.\n",
370 else if (CFStringHasPrefix(type
, registered_name_type_prefix
))
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
),
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
));
388 format
= register_format(RegisterClipboardFormatW(name
), type
);
390 ERR("Failed to register format for type %s name %s\n", debugstr_cf(type
), debugstr_w(name
));
392 HeapFree(GetProcessHeap(), 0, name
);
395 TRACE(" -> %p/%s\n", format
, debugstr_format(format
? format
->format_id
: 0));
400 /**************************************************************************
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
407 static HANDLE
convert_text(const void *src
, int src_len
, UINT src_cp
, UINT dest_cp
)
415 if (src_cp
== (UINT
)-1)
418 wstr_len
= src_len
/ sizeof(WCHAR
);
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;
432 if (dest_cp
== (UINT
)-1)
434 handle
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, wstr_len
* sizeof(WCHAR
));
435 if (handle
&& (p
= GlobalLock(handle
)))
437 memcpy(p
, wstr
, wstr_len
* sizeof(WCHAR
));
438 GlobalUnlock(handle
);
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
);
450 if (handle
&& (p
= GlobalLock(handle
)))
452 WideCharToMultiByte(dest_cp
, 0, wstr
, wstr_len
, p
, len
, NULL
, NULL
);
454 GlobalUnlock(handle
);
463 /**************************************************************************
464 * convert_unicodetext_to_codepage
466 static HANDLE
convert_unicodetext_to_codepage(HANDLE unicode_handle
, UINT cp
)
468 LPWSTR unicode_string
= GlobalLock(unicode_handle
);
473 ret
= convert_text(unicode_string
, GlobalSize(unicode_handle
), -1, cp
);
474 GlobalUnlock(unicode_handle
);
481 /***********************************************************************
484 * Return the size of the bitmap info structure including color table.
486 static int bitmap_info_size(const BITMAPINFO
*info
, WORD coloruse
)
488 unsigned int colors
, size
, masks
= 0;
490 if (info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
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
));
497 else /* assume BITMAPINFOHEADER */
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
));
509 /***********************************************************************
510 * create_dib_from_bitmap
512 * Allocates a packed DIB and copies the bitmap data into it.
514 static HGLOBAL
create_dib_from_bitmap(HBITMAP hBmp
)
520 LPBITMAPINFOHEADER pbmiHeader
;
521 unsigned int cDataSize
, cPackedSize
, OffsetBits
;
524 if (!GetObjectW(hBmp
, sizeof(bmp
), &bmp
)) return 0;
527 * A packed DIB contains a BITMAPINFO structure followed immediately by
528 * an optional color palette and the pixel data.
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)
536 /* Get the offset to the bits */
537 OffsetBits
= cPackedSize
- cDataSize
;
539 /* Allocate the packed DIB */
540 TRACE("\tAllocating packed DIB of size %d\n", cPackedSize
);
541 hPackedDIB
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, cPackedSize
);
544 WARN("Could not allocate packed DIB!\n");
548 /* A packed DIB starts with a BITMAPINFOHEADER */
549 pPackedDIB
= GlobalLock(hPackedDIB
);
550 pbmiHeader
= (LPBITMAPINFOHEADER
)pPackedDIB
;
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;
564 /* Retrieve the DIB bits from the bitmap and fill in the
565 * DIB color table if present */
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
);
577 /* Cleanup if GetDIBits failed */
578 if (nLinesCopied
!= bmp
.bmHeight
)
580 TRACE("\tGetDIBits returned %d. Actual lines=%d\n", nLinesCopied
, bmp
.bmHeight
);
581 GlobalFree(hPackedDIB
);
588 /**************************************************************************
589 * import_clipboard_data
591 * Generic import clipboard data routine.
593 static HANDLE
import_clipboard_data(CFDataRef data
)
595 HANDLE data_handle
= NULL
;
597 size_t len
= CFDataGetLength(data
);
602 /* Turn on the DDESHARE flag to enable shared 32 bit memory */
603 data_handle
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, len
);
607 if ((p
= GlobalLock(data_handle
)))
609 memcpy(p
, CFDataGetBytePtr(data
), len
);
610 GlobalUnlock(data_handle
);
614 GlobalFree(data_handle
);
623 /**************************************************************************
624 * import_bmp_to_bitmap
626 * Import BMP data, converting to CF_BITMAP format.
628 static HANDLE
import_bmp_to_bitmap(CFDataRef data
)
631 HANDLE dib
= import_bmp_to_dib(data
);
634 if (dib
&& (bmi
= GlobalLock(dib
)))
641 offset
= bitmap_info_size(bmi
, DIB_RGB_COLORS
);
643 ret
= CreateDIBitmap(hdc
, &bmi
->bmiHeader
, CBM_INIT
, (LPBYTE
)bmi
+ offset
,
644 bmi
, DIB_RGB_COLORS
);
647 ReleaseDC(NULL
, hdc
);
655 /**************************************************************************
658 * Import BMP data, converting to CF_DIB format. This just entails
659 * stripping the BMP file format header.
661 static HANDLE
import_bmp_to_dib(CFDataRef data
)
664 BITMAPFILEHEADER
*bfh
= (BITMAPFILEHEADER
*)CFDataGetBytePtr(data
);
665 CFIndex len
= CFDataGetLength(data
);
667 if (len
>= sizeof(*bfh
) + sizeof(BITMAPCOREHEADER
) &&
668 bfh
->bfType
== 0x4d42 /* "BM" */)
670 BITMAPINFO
*bmi
= (BITMAPINFO
*)(bfh
+ 1);
674 ret
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, len
);
675 if (!ret
|| !(p
= GlobalLock(ret
)))
689 /**************************************************************************
690 * import_nsfilenames_to_hdrop
692 * Import NSFilenamesPboardType data, converting the property-list-
693 * serialized array of path strings to CF_HDROP.
695 static HANDLE
import_nsfilenames_to_hdrop(CFDataRef data
)
702 WCHAR
**paths
= NULL
;
703 DROPFILES
* dropfiles
;
706 TRACE("data %s\n", debugstr_cf(data
));
708 names
= (CFArrayRef
)CFPropertyListCreateWithData(NULL
, data
, kCFPropertyListImmutable
,
710 if (!names
|| CFGetTypeID(names
) != CFArrayGetTypeID())
712 WARN("failed to interpret data as a CFArray\n");
716 count
= CFArrayGetCount(names
);
719 for (i
= 0; i
< count
; i
++)
722 CFStringRef name
= (CFStringRef
)CFArrayGetValueAtIndex(names
, i
);
723 TRACE(" %s\n", debugstr_cf(name
));
724 if (CFGetTypeID(name
) != CFStringGetTypeID())
726 WARN("non-string in array\n");
730 this_len
= CFStringGetMaximumSizeOfFileSystemRepresentation(name
);
735 buffer
= HeapAlloc(GetProcessHeap(), 0, len
);
738 WARN("failed to allocate buffer for file-system representations\n");
742 paths
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, count
* sizeof(paths
[0]));
745 WARN("failed to allocate array of DOS paths\n");
749 for (i
= 0; i
< count
; i
++)
751 CFStringRef name
= (CFStringRef
)CFArrayGetValueAtIndex(names
, i
);
752 if (!CFStringGetFileSystemRepresentation(name
, buffer
, len
))
754 WARN("failed to get file-system representation for %s\n", debugstr_cf(name
));
757 paths
[i
] = wine_get_dos_file_name(buffer
);
760 WARN("failed to get DOS path for %s\n", debugstr_a(buffer
));
765 len
= 1; /* for the terminating null */
766 for (i
= 0; i
< count
; i
++)
767 len
+= strlenW(paths
[i
]) + 1;
769 hdrop
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, sizeof(*dropfiles
) + len
* sizeof(WCHAR
));
770 if (!hdrop
|| !(dropfiles
= GlobalLock(hdrop
)))
772 WARN("failed to allocate HDROP\n");
778 dropfiles
->pFiles
= sizeof(*dropfiles
);
781 dropfiles
->fNC
= FALSE
;
782 dropfiles
->fWide
= TRUE
;
784 p
= (WCHAR
*)(dropfiles
+ 1);
785 for (i
= 0; i
< count
; i
++)
787 strcpyW(p
, paths
[i
]);
797 for (i
= 0; i
< count
; i
++)
798 HeapFree(GetProcessHeap(), 0, paths
[i
]);
799 HeapFree(GetProcessHeap(), 0, paths
);
801 HeapFree(GetProcessHeap(), 0, buffer
);
802 if (names
) CFRelease(names
);
807 /**************************************************************************
808 * import_oemtext_to_text
810 * Import CF_OEMTEXT data, converting the string to CF_TEXT.
812 static HANDLE
import_oemtext_to_text(CFDataRef data
)
814 return convert_text(CFDataGetBytePtr(data
), CFDataGetLength(data
), CP_OEMCP
, CP_ACP
);
818 /**************************************************************************
819 * import_oemtext_to_unicodetext
821 * Import CF_OEMTEXT data, converting the string to CF_UNICODETEXT.
823 static HANDLE
import_oemtext_to_unicodetext(CFDataRef data
)
825 return convert_text(CFDataGetBytePtr(data
), CFDataGetLength(data
), CP_OEMCP
, -1);
829 /**************************************************************************
830 * import_text_to_oemtext
832 * Import CF_TEXT data, converting the string to CF_OEMTEXT.
834 static HANDLE
import_text_to_oemtext(CFDataRef data
)
836 return convert_text(CFDataGetBytePtr(data
), CFDataGetLength(data
), CP_ACP
, CP_OEMCP
);
840 /**************************************************************************
841 * import_text_to_unicodetext
843 * Import CF_TEXT data, converting the string to CF_UNICODETEXT.
845 static HANDLE
import_text_to_unicodetext(CFDataRef data
)
847 return convert_text(CFDataGetBytePtr(data
), CFDataGetLength(data
), CP_ACP
, -1);
851 /**************************************************************************
852 * import_unicodetext_to_oemtext
854 * Import a CF_UNICODETEXT string, converting the string to CF_OEMTEXT.
856 static HANDLE
import_unicodetext_to_oemtext(CFDataRef data
)
858 return convert_text(CFDataGetBytePtr(data
), CFDataGetLength(data
), -1, CP_OEMCP
);
862 /**************************************************************************
863 * import_unicodetext_to_text
865 * Import a CF_UNICODETEXT string, converting the string to CF_TEXT.
867 static HANDLE
import_unicodetext_to_text(CFDataRef data
)
869 return convert_text(CFDataGetBytePtr(data
), CFDataGetLength(data
), -1, CP_ACP
);
873 /**************************************************************************
874 * import_utf8_to_oemtext
876 * Import a UTF-8 string, converting the string to CF_OEMTEXT.
878 static HANDLE
import_utf8_to_oemtext(CFDataRef data
)
880 HANDLE unicode_handle
= import_utf8_to_unicodetext(data
);
881 HANDLE ret
= convert_unicodetext_to_codepage(unicode_handle
, CP_OEMCP
);
883 GlobalFree(unicode_handle
);
888 /**************************************************************************
889 * import_utf8_to_text
891 * Import a UTF-8 string, converting the string to CF_TEXT.
893 static HANDLE
import_utf8_to_text(CFDataRef data
)
895 HANDLE unicode_handle
= import_utf8_to_unicodetext(data
);
896 HANDLE ret
= convert_unicodetext_to_codepage(unicode_handle
, CP_ACP
);
898 GlobalFree(unicode_handle
);
903 /**************************************************************************
904 * import_utf8_to_unicodetext
906 * Import a UTF-8 string, converting the string to CF_UNICODETEXT.
908 static HANDLE
import_utf8_to_unicodetext(CFDataRef data
)
911 unsigned long data_len
;
912 unsigned long new_lines
= 0;
915 HANDLE unicode_handle
= NULL
;
917 src
= CFDataGetBytePtr(data
);
918 data_len
= CFDataGetLength(data
);
919 for (i
= 0; i
< data_len
; i
++)
925 if ((dst
= HeapAlloc(GetProcessHeap(), 0, data_len
+ new_lines
+ 1)))
929 for (i
= 0, j
= 0; i
< data_len
; i
++)
938 count
= MultiByteToWideChar(CP_UTF8
, 0, dst
, -1, NULL
, 0);
939 unicode_handle
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, count
* sizeof(WCHAR
));
943 WCHAR
*textW
= GlobalLock(unicode_handle
);
944 MultiByteToWideChar(CP_UTF8
, 0, dst
, -1, textW
, count
);
945 GlobalUnlock(unicode_handle
);
948 HeapFree(GetProcessHeap(), 0, dst
);
951 return unicode_handle
;
955 /**************************************************************************
956 * export_clipboard_data
958 * Generic export clipboard data routine.
960 static CFDataRef
export_clipboard_data(HANDLE data
)
966 len
= GlobalSize(data
);
967 src
= GlobalLock(data
);
968 if (!src
) return NULL
;
970 ret
= CFDataCreate(NULL
, src
, len
);
977 /**************************************************************************
978 * export_bitmap_to_bmp
980 * Export CF_BITMAP to BMP file format.
982 static CFDataRef
export_bitmap_to_bmp(HANDLE data
)
984 CFDataRef ret
= NULL
;
987 dib
= create_dib_from_bitmap(data
);
990 ret
= export_dib_to_bmp(dib
);
998 /**************************************************************************
999 * export_codepage_to_utf8
1001 * Export string data in a specified codepage to UTF-8.
1003 static CFDataRef
export_codepage_to_utf8(HANDLE data
, UINT cp
)
1005 CFDataRef ret
= NULL
;
1008 if ((str
= GlobalLock(data
)))
1010 HANDLE unicode
= convert_text(str
, GlobalSize(data
), cp
, -1);
1012 ret
= export_unicodetext_to_utf8(unicode
);
1014 GlobalFree(unicode
);
1022 /**************************************************************************
1025 * Export CF_DIB to BMP file format. This just entails prepending a BMP
1026 * file format header to the data.
1028 static CFDataRef
export_dib_to_bmp(HANDLE data
)
1030 CFMutableDataRef ret
= NULL
;
1033 BITMAPFILEHEADER bfh
;
1035 dibdata
= GlobalLock(data
);
1039 len
= sizeof(bfh
) + GlobalSize(data
);
1040 ret
= CFDataCreateMutable(NULL
, len
);
1043 bfh
.bfType
= 0x4d42; /* "BM" */
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
));
1050 /* rest of bitmap is the same as the packed dib */
1051 CFDataAppendBytes(ret
, (UInt8
*)dibdata
, len
- sizeof(bfh
));
1060 /**************************************************************************
1061 * export_hdrop_to_filenames
1063 * Export CF_HDROP to NSFilenamesPboardType data, which is a CFArray of
1064 * CFStrings (holding Unix paths) which is serialized as a property list.
1066 static CFDataRef
export_hdrop_to_filenames(HANDLE data
)
1068 CFDataRef ret
= NULL
;
1069 DROPFILES
*dropfiles
;
1070 CFMutableArrayRef filenames
= NULL
;
1072 WCHAR
*buffer
= NULL
;
1073 size_t buffer_len
= 0;
1075 TRACE("data %p\n", data
);
1077 if (!(dropfiles
= GlobalLock(data
)))
1079 WARN("failed to lock data %p\n", data
);
1083 filenames
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1086 WARN("failed to create filenames array\n");
1090 p
= (char*)dropfiles
+ dropfiles
->pFiles
;
1091 while (dropfiles
->fWide
? *(WCHAR
*)p
: *(char*)p
)
1094 CFStringRef filename
;
1096 TRACE(" %s\n", dropfiles
->fWide
? debugstr_w(p
) : debugstr_a(p
));
1098 if (dropfiles
->fWide
)
1099 unixname
= wine_get_unix_file_name(p
);
1102 int len
= MultiByteToWideChar(CP_ACP
, 0, p
, -1, NULL
, 0);
1105 if (len
> buffer_len
)
1107 HeapFree(GetProcessHeap(), 0, buffer
);
1108 buffer_len
= len
* 2;
1109 buffer
= HeapAlloc(GetProcessHeap(), 0, buffer_len
* sizeof(*buffer
));
1112 MultiByteToWideChar(CP_ACP
, 0, p
, -1, buffer
, buffer_len
);
1113 unixname
= wine_get_unix_file_name(buffer
);
1120 WARN("failed to convert DOS path to Unix: %s\n",
1121 dropfiles
->fWide
? debugstr_w(p
) : debugstr_a(p
));
1125 if (dropfiles
->fWide
)
1126 p
= (WCHAR
*)p
+ strlenW(p
) + 1;
1128 p
= (char*)p
+ strlen(p
) + 1;
1130 filename
= CFStringCreateWithFileSystemRepresentation(NULL
, unixname
);
1131 HeapFree(GetProcessHeap(), 0, unixname
);
1134 WARN("failed to create CFString from Unix path %s\n", debugstr_a(unixname
));
1138 CFArrayAppendValue(filenames
, filename
);
1139 CFRelease(filename
);
1142 ret
= CFPropertyListCreateData(NULL
, filenames
, kCFPropertyListXMLFormat_v1_0
, 0, NULL
);
1145 HeapFree(GetProcessHeap(), 0, buffer
);
1147 if (filenames
) CFRelease(filenames
);
1148 TRACE(" -> %s\n", debugstr_cf(ret
));
1153 /**************************************************************************
1154 * export_oemtext_to_utf8
1156 * Export CF_OEMTEXT to UTF-8.
1158 static CFDataRef
export_oemtext_to_utf8(HANDLE data
)
1160 return export_codepage_to_utf8(data
, CP_OEMCP
);
1164 /**************************************************************************
1165 * export_text_to_utf8
1167 * Export CF_TEXT to UTF-8.
1169 static CFDataRef
export_text_to_utf8(HANDLE data
)
1171 return export_codepage_to_utf8(data
, CP_ACP
);
1175 /**************************************************************************
1176 * export_unicodetext_to_utf8
1178 * Export CF_UNICODETEXT to UTF-8.
1180 static CFDataRef
export_unicodetext_to_utf8(HANDLE data
)
1182 CFMutableDataRef ret
;
1186 src
= GlobalLock(data
);
1187 if (!src
) return NULL
;
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
);
1197 CFDataSetLength(ret
, dst_len
);
1198 dst
= (LPSTR
)CFDataGetMutableBytePtr(ret
);
1199 WideCharToMultiByte(CP_UTF8
, 0, src
, -1, dst
, dst_len
, NULL
, NULL
);
1201 /* Remove carriage returns */
1202 for (i
= 0, j
= 0; i
< dst_len
; i
++)
1204 if (dst
[i
] == '\r' &&
1205 (i
+ 1 >= dst_len
|| dst
[i
+ 1] == '\n' || dst
[i
+ 1] == '\0'))
1209 CFDataSetLength(ret
, j
);
1217 /**************************************************************************
1218 * get_clipboard_info
1220 static BOOL
get_clipboard_info(LPCLIPBOARDINFO cbinfo
)
1224 SERVER_START_REQ(set_clipboard_info
)
1228 if (wine_server_call_err(req
))
1230 ERR("Failed to get clipboard owner.\n");
1234 cbinfo
->hwnd_owner
= wine_server_ptr_handle(reply
->old_owner
);
1235 cbinfo
->flags
= reply
->flags
;
1246 /**************************************************************************
1249 static BOOL
release_ownership(void)
1253 SERVER_START_REQ(set_clipboard_info
)
1255 req
->flags
= SET_CB_RELOWNER
| SET_CB_SEQNO
;
1257 if (wine_server_call_err(req
))
1258 ERR("Failed to set clipboard.\n");
1268 /**************************************************************************
1269 * macdrv_get_pasteboard_data
1271 HANDLE
macdrv_get_pasteboard_data(CFTypeRef pasteboard
, UINT desired_format
)
1276 CFStringRef type
, best_type
;
1277 WINE_CLIPFORMAT
* best_format
= NULL
;
1280 TRACE("pasteboard %p, desired_format %s\n", pasteboard
, debugstr_format(desired_format
));
1282 types
= macdrv_copy_pasteboard_types(pasteboard
);
1285 WARN("Failed to copy pasteboard types\n");
1289 count
= CFArrayGetCount(types
);
1290 TRACE("got %ld types\n", count
);
1292 for (i
= 0; (!best_format
|| best_format
->synthesized
) && i
< count
; i
++)
1294 WINE_CLIPFORMAT
* format
;
1296 type
= CFArrayGetValueAtIndex(types
, i
);
1299 while ((!best_format
|| best_format
->synthesized
) && (format
= format_for_type(format
, type
)))
1301 TRACE("for type %s got format %p/%s\n", debugstr_cf(type
), format
, debugstr_format(format
? format
->format_id
: 0));
1303 if (format
->format_id
== desired_format
)
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
)
1310 best_format
= format
;
1318 CFDataRef pasteboard_data
= macdrv_copy_pasteboard_data(pasteboard
, best_type
);
1320 TRACE("got pasteboard data for type %s: %s\n", debugstr_cf(best_type
), debugstr_cf(pasteboard_data
));
1322 if (pasteboard_data
)
1324 data
= best_format
->import_func(pasteboard_data
);
1325 CFRelease(pasteboard_data
);
1330 TRACE(" -> %p\n", data
);
1335 /**************************************************************************
1336 * macdrv_pasteboard_has_format
1338 BOOL
macdrv_pasteboard_has_format(CFTypeRef pasteboard
, UINT desired_format
)
1345 TRACE("pasteboard %p, desired_format %s\n", pasteboard
, debugstr_format(desired_format
));
1347 types
= macdrv_copy_pasteboard_types(pasteboard
);
1350 WARN("Failed to copy pasteboard types\n");
1354 count
= CFArrayGetCount(types
);
1355 TRACE("got %d types\n", count
);
1357 for (i
= 0; !found
&& i
< count
; i
++)
1359 CFStringRef type
= CFArrayGetValueAtIndex(types
, i
);
1360 WINE_CLIPFORMAT
* format
;
1363 while (!found
&& (format
= format_for_type(format
, type
)))
1365 TRACE("for type %s got format %s\n", debugstr_cf(type
), debugstr_format(format
->format_id
));
1367 if (format
->format_id
== desired_format
)
1373 TRACE(" -> %d\n", found
);
1378 /**************************************************************************
1379 * macdrv_copy_pasteboard_formats
1381 CFArrayRef
macdrv_copy_pasteboard_formats(CFTypeRef pasteboard
)
1385 CFMutableArrayRef formats
;
1388 TRACE("pasteboard %p\n", pasteboard
);
1390 types
= macdrv_copy_pasteboard_types(pasteboard
);
1393 WARN("Failed to copy pasteboard types\n");
1397 count
= CFArrayGetCount(types
);
1398 TRACE("got %ld types\n", count
);
1406 formats
= CFArrayCreateMutable(NULL
, 0, NULL
);
1409 WARN("Failed to allocate formats array\n");
1414 for (i
= 0; i
< count
; i
++)
1416 CFStringRef type
= CFArrayGetValueAtIndex(types
, i
);
1417 WINE_CLIPFORMAT
* format
;
1420 while ((format
= format_for_type(format
, type
)))
1422 TRACE("for type %s got format %p/%s\n", debugstr_cf(type
), format
, debugstr_format(format
->format_id
));
1424 if (format
->synthesized
)
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
);
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
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
);
1446 TRACE(" -> %s\n", debugstr_cf(formats
));
1451 /**************************************************************************
1452 * check_clipboard_ownership
1454 static void check_clipboard_ownership(HWND
*owner
)
1456 CLIPBOARDINFO cbinfo
;
1458 if (owner
) *owner
= NULL
;
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
))
1464 if (!(cbinfo
.flags
& CB_OPEN
) && !macdrv_is_pasteboard_owner())
1466 TRACE("Lost clipboard ownership\n");
1468 if (OpenClipboard(cbinfo
.hwnd_owner
))
1470 /* Destroy private objects */
1471 SendMessageW(cbinfo
.hwnd_owner
, WM_DESTROYCLIPBOARD
, 0, 0);
1473 /* Give up ownership of the windows clipboard */
1474 release_ownership();
1479 *owner
= cbinfo
.hwnd_owner
;
1484 /**************************************************************************
1485 * Mac User Driver Clipboard Exports
1486 **************************************************************************/
1489 /**************************************************************************
1490 * AcquireClipboard (MACDRV.@)
1492 int CDECL
macdrv_AcquireClipboard(HWND hwnd
)
1494 TRACE("hwnd %p\n", hwnd
);
1495 check_clipboard_ownership(NULL
);
1500 /**************************************************************************
1501 * CountClipboardFormats (MACDRV.@)
1503 INT CDECL
macdrv_CountClipboardFormats(void)
1505 CFMutableSetRef seen_formats
;
1512 check_clipboard_ownership(NULL
);
1514 seen_formats
= CFSetCreateMutable(NULL
, 0, NULL
);
1517 WARN("Failed to allocate set to track seen formats\n");
1521 types
= macdrv_copy_pasteboard_types(NULL
);
1524 WARN("Failed to copy pasteboard types\n");
1525 CFRelease(seen_formats
);
1529 count
= CFArrayGetCount(types
);
1530 TRACE("got %ld types\n", count
);
1532 for (i
= 0; i
< count
; i
++)
1534 CFStringRef type
= CFArrayGetValueAtIndex(types
, i
);
1535 WINE_CLIPFORMAT
* format
;
1538 while ((format
= format_for_type(format
, type
)))
1540 TRACE("for type %s got format %p/%s\n", debugstr_cf(type
), format
, debugstr_format(format
->format_id
));
1542 if (!CFSetContainsValue(seen_formats
, (void*)format
->format_id
))
1545 CFSetAddValue(seen_formats
, (void*)format
->format_id
);
1550 CFRelease(seen_formats
);
1551 TRACE(" -> %d\n", ret
);
1556 /**************************************************************************
1557 * EmptyClipboard (MACDRV.@)
1559 * Empty cached clipboard data.
1561 void CDECL
macdrv_EmptyClipboard(BOOL keepunowned
)
1563 TRACE("keepunowned %d\n", keepunowned
);
1564 macdrv_clear_pasteboard();
1568 /**************************************************************************
1569 * EndClipboardUpdate (MACDRV.@)
1571 void CDECL
macdrv_EndClipboardUpdate(void)
1574 check_clipboard_ownership(NULL
);
1578 /**************************************************************************
1579 * EnumClipboardFormats (MACDRV.@)
1581 UINT CDECL
macdrv_EnumClipboardFormats(UINT prev_format
)
1587 TRACE("prev_format %s\n", debugstr_format(prev_format
));
1588 check_clipboard_ownership(NULL
);
1592 CFArrayRef formats
= macdrv_copy_pasteboard_formats(NULL
);
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);
1605 CFArrayRef types
= macdrv_copy_pasteboard_types(NULL
);
1608 count
= CFArrayGetCount(types
);
1609 TRACE("got %ld types\n", count
);
1613 CFStringRef type
= CFArrayGetValueAtIndex(types
, 0);
1614 WINE_CLIPFORMAT
*format
= format_for_type(NULL
, type
);
1616 ret
= format
? format
->format_id
: 0;
1622 WARN("Failed to copy pasteboard types\n");
1625 TRACE(" -> %u\n", ret
);
1630 /**************************************************************************
1631 * GetClipboardData (MACDRV.@)
1633 HANDLE CDECL
macdrv_GetClipboardData(UINT desired_format
)
1635 check_clipboard_ownership(NULL
);
1637 return macdrv_get_pasteboard_data(NULL
, desired_format
);
1641 /**************************************************************************
1642 * IsClipboardFormatAvailable (MACDRV.@)
1644 BOOL CDECL
macdrv_IsClipboardFormatAvailable(UINT desired_format
)
1646 check_clipboard_ownership(NULL
);
1647 return macdrv_pasteboard_has_format(NULL
, desired_format
);
1651 /**************************************************************************
1652 * SetClipboardData (MACDRV.@)
1654 BOOL CDECL
macdrv_SetClipboardData(UINT format_id
, HANDLE data
, BOOL owner
)
1657 macdrv_window window
;
1658 WINE_CLIPFORMAT
*format
;
1659 CFDataRef cfdata
= NULL
;
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
);
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;
1670 if (&format
->entry
== &format_list
&& !(format
= insert_clipboard_format(format_id
, NULL
)))
1672 WARN("Failed to register clipboard format %s\n", debugstr_format(format_id
));
1676 /* Export the data to the Mac pasteboard. */
1679 if (!format
->export_func
|| !(cfdata
= format
->export_func(data
)))
1681 WARN("Failed to export %s data to type %s\n", debugstr_format(format_id
), debugstr_cf(format
->type
));
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
));
1690 WARN("Failed to set pasteboard data for type %s: %s\n", debugstr_cf(format
->type
), debugstr_cf(cfdata
));
1691 if (cfdata
) CFRelease(cfdata
);
1695 if (cfdata
) CFRelease(cfdata
);
1697 /* Find any other formats for this format_id (the exportable synthesized ones). */
1698 LIST_FOR_EACH_ENTRY(format
, &format_list
, WINE_CLIPFORMAT
, entry
)
1700 if (format
->format_id
== format_id
&& format
->synthesized
&& format
->export_func
)
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
));
1707 cfdata
= format
->export_func(data
);
1710 WARN("Failed to export %s data to type %s\n", debugstr_format(format
->format_id
), debugstr_cf(format
->type
));
1717 if (macdrv_set_pasteboard_data(format
->type
, cfdata
, window
))
1718 TRACE(" ... set pasteboard data: %s\n", debugstr_cf(cfdata
));
1720 WARN(" ... failed to set pasteboard data: %s\n", debugstr_cf(cfdata
));
1722 if (cfdata
) CFRelease(cfdata
);
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
)
1737 else if (format_id
== CF_METAFILEPICT
)
1739 DeleteMetaFile(((METAFILEPICT
*)GlobalLock(data
))->hMF
);
1742 else if (format_id
== CF_ENHMETAFILE
)
1744 DeleteEnhMetaFile(data
);
1746 else if (format_id
< CF_PRIVATEFIRST
|| CF_PRIVATELAST
< format_id
)
1756 /**************************************************************************
1757 * MACDRV Private Clipboard Exports
1758 **************************************************************************/
1761 /**************************************************************************
1762 * macdrv_clipboard_process_attach
1764 void macdrv_clipboard_process_attach(void)
1767 WINE_CLIPFORMAT
*format
;
1769 /* Register built-in formats */
1770 for (i
= 0; i
< sizeof(builtin_format_ids
)/sizeof(builtin_format_ids
[0]); i
++)
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
);
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
++)
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
);
1795 /**************************************************************************
1796 * query_pasteboard_data
1798 BOOL
query_pasteboard_data(HWND hwnd
, CFStringRef type
)
1801 CLIPBOARDINFO cbinfo
;
1802 WINE_CLIPFORMAT
* format
;
1803 CFArrayRef types
= NULL
;
1806 TRACE("hwnd %p type %s\n", hwnd
, debugstr_cf(type
));
1808 if (get_clipboard_info(&cbinfo
))
1809 hwnd
= cbinfo
.hwnd_owner
;
1812 while ((format
= format_for_type(format
, type
)))
1814 WINE_CLIPFORMAT
* base_format
;
1816 TRACE("for type %s got format %p/%s\n", debugstr_cf(type
), format
, debugstr_format(format
->format_id
));
1818 if (!format
->synthesized
)
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);
1828 types
= macdrv_copy_pasteboard_types(NULL
);
1831 WARN("Failed to copy pasteboard types\n");
1835 range
= CFRangeMake(0, CFArrayGetCount(types
));
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
)
1848 if (base_format
->format_id
== format
->format_id
&& !base_format
->synthesized
&&
1849 CFArrayContainsValue(types
, range
, base_format
->type
))
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);
1860 if (types
) CFRelease(types
);