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
);
85 static HANDLE
import_utf16_to_oemtext(CFDataRef data
);
86 static HANDLE
import_utf16_to_text(CFDataRef data
);
87 static HANDLE
import_utf16_to_unicodetext(CFDataRef data
);
89 static CFDataRef
export_clipboard_data(HANDLE data
);
90 static CFDataRef
export_bitmap_to_bmp(HANDLE data
);
91 static CFDataRef
export_dib_to_bmp(HANDLE data
);
92 static CFDataRef
export_hdrop_to_filenames(HANDLE data
);
93 static CFDataRef
export_oemtext_to_utf8(HANDLE data
);
94 static CFDataRef
export_oemtext_to_utf16(HANDLE data
);
95 static CFDataRef
export_text_to_utf8(HANDLE data
);
96 static CFDataRef
export_text_to_utf16(HANDLE data
);
97 static CFDataRef
export_unicodetext_to_utf8(HANDLE data
);
98 static CFDataRef
export_unicodetext_to_utf16(HANDLE data
);
101 /**************************************************************************
103 **************************************************************************/
105 /* Clipboard formats */
106 static struct list format_list
= LIST_INIT(format_list
);
108 /* There are two naming schemes involved and we want to have a mapping between
109 them. There are Win32 clipboard format names and there are Mac pasteboard
112 The Win32 standard clipboard formats don't have names, but they are associated
113 with Mac pasteboard types through the following tables, which are used to
114 initialize the format_list. Where possible, the standard clipboard formats
115 are mapped to predefined pasteboard type UTIs. Otherwise, we create Wine-
116 specific types of the form "org.winehq.builtin.<format>", where <format> is
117 the name of the symbolic constant for the format minus "CF_" and lowercased.
118 E.g. CF_BITMAP -> org.winehq.builtin.bitmap.
120 Win32 clipboard formats which originate in a Windows program may be registered
121 with an arbitrary name. We construct a Mac pasteboard type from these by
122 prepending "org.winehq.registered." to the registered name.
124 Likewise, Mac pasteboard types which originate in other apps may have
125 arbitrary type strings. We construct a Win32 clipboard format name from
126 these by prepending "org.winehq.mac-type." to the Mac pasteboard type.
129 Win32 clipboard format names:
130 <none> standard clipboard format; maps via
131 format_list to either a predefined Mac UTI
132 or org.winehq.builtin.<format>.
133 org.winehq.mac-type.<Mac type> representation of Mac type in Win32 land;
135 <other> name registered within Win32 land; maps to
136 org.winehq.registered.<other>
137 Mac pasteboard type names:
138 org.winehq.builtin.<format ID> representation of Win32 standard clipboard
139 format for which there was no corresponding
140 predefined Mac UTI; maps via format_list
141 org.winehq.registered.<format name> representation of Win32 registered
142 clipboard format name; maps to <format name>
143 <other> Mac pasteboard type originating with system
144 or other apps; either maps via format_list
145 to a standard clipboard format or maps to
146 org.winehq.mac-type.<other>
153 DRVIMPORTFUNC import
;
154 DRVEXPORTFUNC export
;
156 } builtin_format_ids
[] =
158 { CF_DIBV5
, CFSTR("org.winehq.builtin.dibv5"), import_clipboard_data
, export_clipboard_data
, FALSE
},
159 { CF_DIF
, CFSTR("org.winehq.builtin.dif"), import_clipboard_data
, export_clipboard_data
, FALSE
},
160 { CF_DSPBITMAP
, CFSTR("org.winehq.builtin.dspbitmap"), import_clipboard_data
, export_clipboard_data
, FALSE
},
161 { CF_DSPENHMETAFILE
, CFSTR("org.winehq.builtin.dspenhmetafile"), import_clipboard_data
, export_clipboard_data
, FALSE
},
162 { CF_DSPMETAFILEPICT
, CFSTR("org.winehq.builtin.dspmetafilepict"), import_clipboard_data
, export_clipboard_data
, FALSE
},
163 { CF_DSPTEXT
, CFSTR("org.winehq.builtin.dsptext"), import_clipboard_data
, export_clipboard_data
, FALSE
},
164 { CF_LOCALE
, CFSTR("org.winehq.builtin.locale"), import_clipboard_data
, export_clipboard_data
, FALSE
},
165 { CF_OWNERDISPLAY
, CFSTR("org.winehq.builtin.ownerdisplay"), import_clipboard_data
, export_clipboard_data
, FALSE
},
166 { CF_PALETTE
, CFSTR("org.winehq.builtin.palette"), import_clipboard_data
, export_clipboard_data
, FALSE
},
167 { CF_PENDATA
, CFSTR("org.winehq.builtin.pendata"), import_clipboard_data
, export_clipboard_data
, FALSE
},
168 { CF_RIFF
, CFSTR("org.winehq.builtin.riff"), import_clipboard_data
, export_clipboard_data
, FALSE
},
169 { CF_SYLK
, CFSTR("org.winehq.builtin.sylk"), import_clipboard_data
, export_clipboard_data
, FALSE
},
170 { CF_TIFF
, CFSTR("public.tiff"), import_clipboard_data
, export_clipboard_data
, FALSE
},
171 { CF_WAVE
, CFSTR("com.microsoft.waveform-audio"), import_clipboard_data
, export_clipboard_data
, FALSE
},
173 { CF_UNICODETEXT
, CFSTR("org.winehq.builtin.unicodetext"), import_clipboard_data
, export_clipboard_data
, FALSE
},
174 { CF_TEXT
, CFSTR("org.winehq.builtin.unicodetext"), import_unicodetext_to_text
, NULL
, TRUE
},
175 { CF_OEMTEXT
, CFSTR("org.winehq.builtin.unicodetext"), import_unicodetext_to_oemtext
, NULL
, TRUE
},
177 { CF_TEXT
, CFSTR("org.winehq.builtin.text"), import_clipboard_data
, export_clipboard_data
, FALSE
},
178 { CF_UNICODETEXT
, CFSTR("org.winehq.builtin.text"), import_text_to_unicodetext
, NULL
, TRUE
},
179 { CF_OEMTEXT
, CFSTR("org.winehq.builtin.text"), import_text_to_oemtext
, NULL
, TRUE
},
181 { CF_OEMTEXT
, CFSTR("org.winehq.builtin.oemtext"), import_clipboard_data
, export_clipboard_data
, FALSE
},
182 { CF_UNICODETEXT
, CFSTR("org.winehq.builtin.oemtext"), import_oemtext_to_unicodetext
, NULL
, TRUE
},
183 { CF_TEXT
, CFSTR("org.winehq.builtin.oemtext"), import_oemtext_to_text
, NULL
, TRUE
},
185 { CF_UNICODETEXT
, CFSTR("public.utf8-plain-text"), import_utf8_to_unicodetext
, export_unicodetext_to_utf8
, TRUE
},
186 { CF_TEXT
, CFSTR("public.utf8-plain-text"), import_utf8_to_text
, export_text_to_utf8
, TRUE
},
187 { CF_OEMTEXT
, CFSTR("public.utf8-plain-text"), import_utf8_to_oemtext
, export_oemtext_to_utf8
, TRUE
},
189 { CF_UNICODETEXT
, CFSTR("public.utf16-plain-text"), import_utf16_to_unicodetext
, export_unicodetext_to_utf16
,TRUE
},
190 { CF_TEXT
, CFSTR("public.utf16-plain-text"), import_utf16_to_text
, export_text_to_utf16
, TRUE
},
191 { CF_OEMTEXT
, CFSTR("public.utf16-plain-text"), import_utf16_to_oemtext
, export_oemtext_to_utf16
, TRUE
},
193 { CF_DIB
, CFSTR("org.winehq.builtin.dib"), import_clipboard_data
, export_clipboard_data
, FALSE
},
194 { CF_DIB
, CFSTR("com.microsoft.bmp"), import_bmp_to_dib
, export_dib_to_bmp
, TRUE
},
196 { CF_BITMAP
, CFSTR("org.winehq.builtin.bitmap"), import_bmp_to_bitmap
, export_bitmap_to_bmp
, FALSE
},
197 { CF_BITMAP
, CFSTR("com.microsoft.bmp"), import_bmp_to_bitmap
, export_bitmap_to_bmp
, TRUE
},
199 { CF_HDROP
, CFSTR("org.winehq.builtin.hdrop"), import_clipboard_data
, export_clipboard_data
, FALSE
},
200 { CF_HDROP
, CFSTR("NSFilenamesPboardType"), import_nsfilenames_to_hdrop
, export_hdrop_to_filenames
, TRUE
},
203 static const WCHAR wszRichTextFormat
[] = {'R','i','c','h',' ','T','e','x','t',' ','F','o','r','m','a','t',0};
204 static const WCHAR wszGIF
[] = {'G','I','F',0};
205 static const WCHAR wszJFIF
[] = {'J','F','I','F',0};
206 static const WCHAR wszPNG
[] = {'P','N','G',0};
207 static const WCHAR wszHTMLFormat
[] = {'H','T','M','L',' ','F','o','r','m','a','t',0};
212 DRVIMPORTFUNC import
;
213 DRVEXPORTFUNC export
;
214 } builtin_format_names
[] =
216 { wszRichTextFormat
, CFSTR("public.rtf"), import_clipboard_data
, export_clipboard_data
},
217 { wszGIF
, CFSTR("com.compuserve.gif"), import_clipboard_data
, export_clipboard_data
},
218 { wszJFIF
, CFSTR("public.jpeg"), import_clipboard_data
, export_clipboard_data
},
219 { wszPNG
, CFSTR("public.png"), import_clipboard_data
, export_clipboard_data
},
220 { wszHTMLFormat
, CFSTR("public.html"), import_clipboard_data
, export_clipboard_data
},
221 { CFSTR_SHELLURLW
, CFSTR("public.url"), import_utf8_to_text
, export_text_to_utf8
},
224 /* The prefix prepended to an external Mac pasteboard type to make a Win32 clipboard format name. org.winehq.mac-type. */
225 static const WCHAR mac_type_name_prefix
[] = {'o','r','g','.','w','i','n','e','h','q','.','m','a','c','-','t','y','p','e','.',0};
227 /* The prefix prepended to a Win32 clipboard format name to make a Mac pasteboard type. */
228 static const CFStringRef registered_name_type_prefix
= CFSTR("org.winehq.registered.");
231 /**************************************************************************
232 * Internal Clipboard implementation methods
233 **************************************************************************/
236 * format_list functions
239 /**************************************************************************
242 const char *debugstr_format(UINT id
)
246 if (GetClipboardFormatNameW(id
, buffer
, 256))
247 return wine_dbg_sprintf("0x%04x %s", id
, debugstr_w(buffer
));
251 #define BUILTIN(id) case id: return #id;
254 BUILTIN(CF_METAFILEPICT
)
264 BUILTIN(CF_UNICODETEXT
)
265 BUILTIN(CF_ENHMETAFILE
)
269 BUILTIN(CF_OWNERDISPLAY
)
271 BUILTIN(CF_DSPBITMAP
)
272 BUILTIN(CF_DSPMETAFILEPICT
)
273 BUILTIN(CF_DSPENHMETAFILE
)
275 default: return wine_dbg_sprintf("0x%04x", id
);
280 /**************************************************************************
281 * insert_clipboard_format
283 static WINE_CLIPFORMAT
*insert_clipboard_format(UINT id
, CFStringRef type
)
285 WINE_CLIPFORMAT
*format
;
287 format
= HeapAlloc(GetProcessHeap(), 0, sizeof(*format
));
291 WARN("No more memory for a new format!\n");
294 format
->format_id
= id
;
295 format
->import_func
= import_clipboard_data
;
296 format
->export_func
= export_clipboard_data
;
297 format
->synthesized
= FALSE
;
300 format
->type
= CFStringCreateCopy(NULL
, type
);
305 if (!GetClipboardFormatNameW(format
->format_id
, buffer
, sizeof(buffer
) / sizeof(buffer
[0])))
307 WARN("failed to get name for format %s; error 0x%08x\n", debugstr_format(format
->format_id
), GetLastError());
308 HeapFree(GetProcessHeap(), 0, format
);
312 if (!strncmpW(buffer
, mac_type_name_prefix
, strlenW(mac_type_name_prefix
)))
314 const WCHAR
*p
= buffer
+ strlenW(mac_type_name_prefix
);
315 format
->type
= CFStringCreateWithCharacters(NULL
, (UniChar
*)p
, strlenW(p
));
319 format
->type
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@%S"),
320 registered_name_type_prefix
, buffer
);
324 list_add_tail(&format_list
, &format
->entry
);
326 TRACE("Registering format %s type %s\n", debugstr_format(format
->format_id
),
327 debugstr_cf(format
->type
));
333 /**************************************************************************
336 * Register a custom Mac clipboard format.
338 static WINE_CLIPFORMAT
* register_format(UINT id
, CFStringRef type
)
340 WINE_CLIPFORMAT
*format
;
342 /* walk format chain to see if it's already registered */
343 LIST_FOR_EACH_ENTRY(format
, &format_list
, WINE_CLIPFORMAT
, entry
)
344 if (format
->format_id
== id
) return format
;
346 return insert_clipboard_format(id
, type
);
350 /**************************************************************************
353 static WINE_CLIPFORMAT
* format_for_type(WINE_CLIPFORMAT
*current
, CFStringRef type
)
355 struct list
*ptr
= current
? ¤t
->entry
: &format_list
;
356 WINE_CLIPFORMAT
*format
= NULL
;
358 TRACE("current %p/%s type %s\n", current
, debugstr_format(current
? current
->format_id
: 0), debugstr_cf(type
));
360 while ((ptr
= list_next(&format_list
, ptr
)))
362 format
= LIST_ENTRY(ptr
, WINE_CLIPFORMAT
, entry
);
363 if (CFEqual(format
->type
, type
))
365 TRACE(" -> %p/%s\n", format
, debugstr_format(format
->format_id
));
374 if (CFStringHasPrefix(type
, CFSTR("org.winehq.builtin.")))
376 ERR("Shouldn't happen. Built-in type %s should have matched something in format list.\n",
380 else if (CFStringHasPrefix(type
, registered_name_type_prefix
))
382 int len
= CFStringGetLength(type
) - CFStringGetLength(registered_name_type_prefix
);
383 name
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
));
384 CFStringGetCharacters(type
, CFRangeMake(CFStringGetLength(registered_name_type_prefix
), len
),
390 int len
= strlenW(mac_type_name_prefix
) + CFStringGetLength(type
);
391 name
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
));
392 memcpy(name
, mac_type_name_prefix
, sizeof(mac_type_name_prefix
));
393 CFStringGetCharacters(type
, CFRangeMake(0, CFStringGetLength(type
)),
394 (UniChar
*)name
+ strlenW(mac_type_name_prefix
));
398 format
= register_format(RegisterClipboardFormatW(name
), type
);
400 ERR("Failed to register format for type %s name %s\n", debugstr_cf(type
), debugstr_w(name
));
402 HeapFree(GetProcessHeap(), 0, name
);
405 TRACE(" -> %p/%s\n", format
, debugstr_format(format
? format
->format_id
: 0));
410 /**************************************************************************
413 * Convert string data between code pages or to/from wide characters. The
414 * special value of (UINT)-1 for a code page indicates to use wide
417 static HANDLE
convert_text(const void *src
, int src_len
, UINT src_cp
, UINT dest_cp
)
425 if (src_cp
== (UINT
)-1)
428 wstr_len
= src_len
/ sizeof(WCHAR
);
434 wstr_len
= MultiByteToWideChar(src_cp
, 0, src
, src_len
, NULL
, 0);
435 if (!src_len
|| ((const char*)src
)[src_len
- 1]) wstr_len
+= 1;
436 temp
= HeapAlloc(GetProcessHeap(), 0, wstr_len
* sizeof(WCHAR
));
437 MultiByteToWideChar(src_cp
, 0, src
, src_len
, temp
, wstr_len
);
438 temp
[wstr_len
- 1] = 0;
442 if (dest_cp
== (UINT
)-1)
444 handle
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, wstr_len
* sizeof(WCHAR
));
445 if (handle
&& (p
= GlobalLock(handle
)))
447 memcpy(p
, wstr
, wstr_len
* sizeof(WCHAR
));
448 GlobalUnlock(handle
);
456 len
= WideCharToMultiByte(dest_cp
, 0, wstr
, wstr_len
, NULL
, 0, NULL
, NULL
);
457 if (!wstr_len
|| wstr
[wstr_len
- 1]) len
+= 1;
458 handle
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, len
);
460 if (handle
&& (p
= GlobalLock(handle
)))
462 WideCharToMultiByte(dest_cp
, 0, wstr
, wstr_len
, p
, len
, NULL
, NULL
);
464 GlobalUnlock(handle
);
473 /**************************************************************************
474 * convert_unicodetext_to_codepage
476 static HANDLE
convert_unicodetext_to_codepage(HANDLE unicode_handle
, UINT cp
)
478 LPWSTR unicode_string
= GlobalLock(unicode_handle
);
483 ret
= convert_text(unicode_string
, GlobalSize(unicode_handle
), -1, cp
);
484 GlobalUnlock(unicode_handle
);
491 /***********************************************************************
494 * Return the size of the bitmap info structure including color table.
496 static int bitmap_info_size(const BITMAPINFO
*info
, WORD coloruse
)
498 unsigned int colors
, size
, masks
= 0;
500 if (info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
502 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)info
;
503 colors
= (core
->bcBitCount
<= 8) ? 1 << core
->bcBitCount
: 0;
504 return sizeof(BITMAPCOREHEADER
) + colors
*
505 ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBTRIPLE
) : sizeof(WORD
));
507 else /* assume BITMAPINFOHEADER */
509 colors
= info
->bmiHeader
.biClrUsed
;
510 if (!colors
&& (info
->bmiHeader
.biBitCount
<= 8))
511 colors
= 1 << info
->bmiHeader
.biBitCount
;
512 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
) masks
= 3;
513 size
= max(info
->bmiHeader
.biSize
, sizeof(BITMAPINFOHEADER
) + masks
* sizeof(DWORD
));
514 return size
+ colors
* ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBQUAD
) : sizeof(WORD
));
519 /***********************************************************************
520 * create_dib_from_bitmap
522 * Allocates a packed DIB and copies the bitmap data into it.
524 static HGLOBAL
create_dib_from_bitmap(HBITMAP hBmp
)
530 LPBITMAPINFOHEADER pbmiHeader
;
531 unsigned int cDataSize
, cPackedSize
, OffsetBits
;
534 if (!GetObjectW(hBmp
, sizeof(bmp
), &bmp
)) return 0;
537 * A packed DIB contains a BITMAPINFO structure followed immediately by
538 * an optional color palette and the pixel data.
541 /* Calculate the size of the packed DIB */
542 cDataSize
= abs(bmp
.bmHeight
) * (((bmp
.bmWidth
* bmp
.bmBitsPixel
+ 31) / 8) & ~3);
543 cPackedSize
= sizeof(BITMAPINFOHEADER
)
544 + ((bmp
.bmBitsPixel
<= 8) ? (sizeof(RGBQUAD
) * (1 << bmp
.bmBitsPixel
)) : 0)
546 /* Get the offset to the bits */
547 OffsetBits
= cPackedSize
- cDataSize
;
549 /* Allocate the packed DIB */
550 TRACE("\tAllocating packed DIB of size %d\n", cPackedSize
);
551 hPackedDIB
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, cPackedSize
);
554 WARN("Could not allocate packed DIB!\n");
558 /* A packed DIB starts with a BITMAPINFOHEADER */
559 pPackedDIB
= GlobalLock(hPackedDIB
);
560 pbmiHeader
= (LPBITMAPINFOHEADER
)pPackedDIB
;
562 /* Init the BITMAPINFOHEADER */
563 pbmiHeader
->biSize
= sizeof(BITMAPINFOHEADER
);
564 pbmiHeader
->biWidth
= bmp
.bmWidth
;
565 pbmiHeader
->biHeight
= bmp
.bmHeight
;
566 pbmiHeader
->biPlanes
= 1;
567 pbmiHeader
->biBitCount
= bmp
.bmBitsPixel
;
568 pbmiHeader
->biCompression
= BI_RGB
;
569 pbmiHeader
->biSizeImage
= 0;
570 pbmiHeader
->biXPelsPerMeter
= pbmiHeader
->biYPelsPerMeter
= 0;
571 pbmiHeader
->biClrUsed
= 0;
572 pbmiHeader
->biClrImportant
= 0;
574 /* Retrieve the DIB bits from the bitmap and fill in the
575 * DIB color table if present */
577 nLinesCopied
= GetDIBits(hdc
, /* Handle to device context */
578 hBmp
, /* Handle to bitmap */
579 0, /* First scan line to set in dest bitmap */
580 bmp
.bmHeight
, /* Number of scan lines to copy */
581 pPackedDIB
+ OffsetBits
, /* [out] Address of array for bitmap bits */
582 (LPBITMAPINFO
) pbmiHeader
, /* [out] Address of BITMAPINFO structure */
583 0); /* RGB or palette index */
584 GlobalUnlock(hPackedDIB
);
587 /* Cleanup if GetDIBits failed */
588 if (nLinesCopied
!= bmp
.bmHeight
)
590 TRACE("\tGetDIBits returned %d. Actual lines=%d\n", nLinesCopied
, bmp
.bmHeight
);
591 GlobalFree(hPackedDIB
);
598 /**************************************************************************
599 * import_clipboard_data
601 * Generic import clipboard data routine.
603 static HANDLE
import_clipboard_data(CFDataRef data
)
605 HANDLE data_handle
= NULL
;
607 size_t len
= CFDataGetLength(data
);
612 /* Turn on the DDESHARE flag to enable shared 32 bit memory */
613 data_handle
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, len
);
617 if ((p
= GlobalLock(data_handle
)))
619 memcpy(p
, CFDataGetBytePtr(data
), len
);
620 GlobalUnlock(data_handle
);
624 GlobalFree(data_handle
);
633 /**************************************************************************
634 * import_bmp_to_bitmap
636 * Import BMP data, converting to CF_BITMAP format.
638 static HANDLE
import_bmp_to_bitmap(CFDataRef data
)
641 HANDLE dib
= import_bmp_to_dib(data
);
644 if (dib
&& (bmi
= GlobalLock(dib
)))
651 offset
= bitmap_info_size(bmi
, DIB_RGB_COLORS
);
653 ret
= CreateDIBitmap(hdc
, &bmi
->bmiHeader
, CBM_INIT
, (LPBYTE
)bmi
+ offset
,
654 bmi
, DIB_RGB_COLORS
);
657 ReleaseDC(NULL
, hdc
);
665 /**************************************************************************
668 * Import BMP data, converting to CF_DIB format. This just entails
669 * stripping the BMP file format header.
671 static HANDLE
import_bmp_to_dib(CFDataRef data
)
674 BITMAPFILEHEADER
*bfh
= (BITMAPFILEHEADER
*)CFDataGetBytePtr(data
);
675 CFIndex len
= CFDataGetLength(data
);
677 if (len
>= sizeof(*bfh
) + sizeof(BITMAPCOREHEADER
) &&
678 bfh
->bfType
== 0x4d42 /* "BM" */)
680 BITMAPINFO
*bmi
= (BITMAPINFO
*)(bfh
+ 1);
684 ret
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, len
);
685 if (!ret
|| !(p
= GlobalLock(ret
)))
699 /**************************************************************************
700 * import_nsfilenames_to_hdrop
702 * Import NSFilenamesPboardType data, converting the property-list-
703 * serialized array of path strings to CF_HDROP.
705 static HANDLE
import_nsfilenames_to_hdrop(CFDataRef data
)
712 WCHAR
**paths
= NULL
;
713 DROPFILES
* dropfiles
;
716 TRACE("data %s\n", debugstr_cf(data
));
718 names
= (CFArrayRef
)CFPropertyListCreateWithData(NULL
, data
, kCFPropertyListImmutable
,
720 if (!names
|| CFGetTypeID(names
) != CFArrayGetTypeID())
722 WARN("failed to interpret data as a CFArray\n");
726 count
= CFArrayGetCount(names
);
729 for (i
= 0; i
< count
; i
++)
732 CFStringRef name
= (CFStringRef
)CFArrayGetValueAtIndex(names
, i
);
733 TRACE(" %s\n", debugstr_cf(name
));
734 if (CFGetTypeID(name
) != CFStringGetTypeID())
736 WARN("non-string in array\n");
740 this_len
= CFStringGetMaximumSizeOfFileSystemRepresentation(name
);
745 buffer
= HeapAlloc(GetProcessHeap(), 0, len
);
748 WARN("failed to allocate buffer for file-system representations\n");
752 paths
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, count
* sizeof(paths
[0]));
755 WARN("failed to allocate array of DOS paths\n");
759 for (i
= 0; i
< count
; i
++)
761 CFStringRef name
= (CFStringRef
)CFArrayGetValueAtIndex(names
, i
);
762 if (!CFStringGetFileSystemRepresentation(name
, buffer
, len
))
764 WARN("failed to get file-system representation for %s\n", debugstr_cf(name
));
767 paths
[i
] = wine_get_dos_file_name(buffer
);
770 WARN("failed to get DOS path for %s\n", debugstr_a(buffer
));
775 len
= 1; /* for the terminating null */
776 for (i
= 0; i
< count
; i
++)
777 len
+= strlenW(paths
[i
]) + 1;
779 hdrop
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, sizeof(*dropfiles
) + len
* sizeof(WCHAR
));
780 if (!hdrop
|| !(dropfiles
= GlobalLock(hdrop
)))
782 WARN("failed to allocate HDROP\n");
788 dropfiles
->pFiles
= sizeof(*dropfiles
);
791 dropfiles
->fNC
= FALSE
;
792 dropfiles
->fWide
= TRUE
;
794 p
= (WCHAR
*)(dropfiles
+ 1);
795 for (i
= 0; i
< count
; i
++)
797 strcpyW(p
, paths
[i
]);
807 for (i
= 0; i
< count
; i
++)
808 HeapFree(GetProcessHeap(), 0, paths
[i
]);
809 HeapFree(GetProcessHeap(), 0, paths
);
811 HeapFree(GetProcessHeap(), 0, buffer
);
812 if (names
) CFRelease(names
);
817 /**************************************************************************
818 * import_oemtext_to_text
820 * Import CF_OEMTEXT data, converting the string to CF_TEXT.
822 static HANDLE
import_oemtext_to_text(CFDataRef data
)
824 return convert_text(CFDataGetBytePtr(data
), CFDataGetLength(data
), CP_OEMCP
, CP_ACP
);
828 /**************************************************************************
829 * import_oemtext_to_unicodetext
831 * Import CF_OEMTEXT data, converting the string to CF_UNICODETEXT.
833 static HANDLE
import_oemtext_to_unicodetext(CFDataRef data
)
835 return convert_text(CFDataGetBytePtr(data
), CFDataGetLength(data
), CP_OEMCP
, -1);
839 /**************************************************************************
840 * import_text_to_oemtext
842 * Import CF_TEXT data, converting the string to CF_OEMTEXT.
844 static HANDLE
import_text_to_oemtext(CFDataRef data
)
846 return convert_text(CFDataGetBytePtr(data
), CFDataGetLength(data
), CP_ACP
, CP_OEMCP
);
850 /**************************************************************************
851 * import_text_to_unicodetext
853 * Import CF_TEXT data, converting the string to CF_UNICODETEXT.
855 static HANDLE
import_text_to_unicodetext(CFDataRef data
)
857 return convert_text(CFDataGetBytePtr(data
), CFDataGetLength(data
), CP_ACP
, -1);
861 /**************************************************************************
862 * import_unicodetext_to_oemtext
864 * Import a CF_UNICODETEXT string, converting the string to CF_OEMTEXT.
866 static HANDLE
import_unicodetext_to_oemtext(CFDataRef data
)
868 return convert_text(CFDataGetBytePtr(data
), CFDataGetLength(data
), -1, CP_OEMCP
);
872 /**************************************************************************
873 * import_unicodetext_to_text
875 * Import a CF_UNICODETEXT string, converting the string to CF_TEXT.
877 static HANDLE
import_unicodetext_to_text(CFDataRef data
)
879 return convert_text(CFDataGetBytePtr(data
), CFDataGetLength(data
), -1, CP_ACP
);
883 /**************************************************************************
884 * import_utf8_to_oemtext
886 * Import a UTF-8 string, converting the string to CF_OEMTEXT.
888 static HANDLE
import_utf8_to_oemtext(CFDataRef data
)
890 HANDLE unicode_handle
= import_utf8_to_unicodetext(data
);
891 HANDLE ret
= convert_unicodetext_to_codepage(unicode_handle
, CP_OEMCP
);
893 GlobalFree(unicode_handle
);
898 /**************************************************************************
899 * import_utf8_to_text
901 * Import a UTF-8 string, converting the string to CF_TEXT.
903 static HANDLE
import_utf8_to_text(CFDataRef data
)
905 HANDLE unicode_handle
= import_utf8_to_unicodetext(data
);
906 HANDLE ret
= convert_unicodetext_to_codepage(unicode_handle
, CP_ACP
);
908 GlobalFree(unicode_handle
);
913 /**************************************************************************
914 * import_utf8_to_unicodetext
916 * Import a UTF-8 string, converting the string to CF_UNICODETEXT.
918 static HANDLE
import_utf8_to_unicodetext(CFDataRef data
)
921 unsigned long data_len
;
922 unsigned long new_lines
= 0;
925 HANDLE unicode_handle
= NULL
;
927 src
= CFDataGetBytePtr(data
);
928 data_len
= CFDataGetLength(data
);
929 for (i
= 0; i
< data_len
; i
++)
935 if ((dst
= HeapAlloc(GetProcessHeap(), 0, data_len
+ new_lines
+ 1)))
939 for (i
= 0, j
= 0; i
< data_len
; i
++)
948 count
= MultiByteToWideChar(CP_UTF8
, 0, dst
, -1, NULL
, 0);
949 unicode_handle
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, count
* sizeof(WCHAR
));
953 WCHAR
*textW
= GlobalLock(unicode_handle
);
954 MultiByteToWideChar(CP_UTF8
, 0, dst
, -1, textW
, count
);
955 GlobalUnlock(unicode_handle
);
958 HeapFree(GetProcessHeap(), 0, dst
);
961 return unicode_handle
;
965 /**************************************************************************
966 * import_utf16_to_oemtext
968 * Import a UTF-16 string, converting the string to CF_OEMTEXT.
970 static HANDLE
import_utf16_to_oemtext(CFDataRef data
)
972 HANDLE unicode_handle
= import_utf16_to_unicodetext(data
);
973 HANDLE ret
= convert_unicodetext_to_codepage(unicode_handle
, CP_OEMCP
);
975 GlobalFree(unicode_handle
);
980 /**************************************************************************
981 * import_utf16_to_text
983 * Import a UTF-16 string, converting the string to CF_TEXT.
985 static HANDLE
import_utf16_to_text(CFDataRef data
)
987 HANDLE unicode_handle
= import_utf16_to_unicodetext(data
);
988 HANDLE ret
= convert_unicodetext_to_codepage(unicode_handle
, CP_ACP
);
990 GlobalFree(unicode_handle
);
995 /**************************************************************************
996 * import_utf16_to_unicodetext
998 * Import a UTF-8 string, converting the string to CF_UNICODETEXT.
1000 static HANDLE
import_utf16_to_unicodetext(CFDataRef data
)
1003 unsigned long data_len
;
1004 unsigned long new_lines
= 0;
1007 HANDLE unicode_handle
;
1009 src
= (const WCHAR
*)CFDataGetBytePtr(data
);
1010 data_len
= CFDataGetLength(data
);
1011 for (i
= 0; i
< data_len
; i
++)
1017 if ((unicode_handle
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, (data_len
+ new_lines
+ 1) * sizeof(WCHAR
))))
1019 dst
= GlobalLock(unicode_handle
);
1021 for (i
= 0, j
= 0; i
< data_len
; i
++)
1030 GlobalUnlock(unicode_handle
);
1033 return unicode_handle
;
1037 /**************************************************************************
1038 * export_clipboard_data
1040 * Generic export clipboard data routine.
1042 static CFDataRef
export_clipboard_data(HANDLE data
)
1048 len
= GlobalSize(data
);
1049 src
= GlobalLock(data
);
1050 if (!src
) return NULL
;
1052 ret
= CFDataCreate(NULL
, src
, len
);
1059 /**************************************************************************
1060 * export_bitmap_to_bmp
1062 * Export CF_BITMAP to BMP file format.
1064 static CFDataRef
export_bitmap_to_bmp(HANDLE data
)
1066 CFDataRef ret
= NULL
;
1069 dib
= create_dib_from_bitmap(data
);
1072 ret
= export_dib_to_bmp(dib
);
1080 /**************************************************************************
1081 * export_codepage_to_utf8
1083 * Export string data in a specified codepage to UTF-8.
1085 static CFDataRef
export_codepage_to_utf8(HANDLE data
, UINT cp
)
1087 CFDataRef ret
= NULL
;
1090 if ((str
= GlobalLock(data
)))
1092 HANDLE unicode
= convert_text(str
, GlobalSize(data
), cp
, -1);
1094 ret
= export_unicodetext_to_utf8(unicode
);
1096 GlobalFree(unicode
);
1104 /**************************************************************************
1105 * export_codepage_to_utf16
1107 * Export string data in a specified codepage to UTF-16.
1109 static CFDataRef
export_codepage_to_utf16(HANDLE data
, UINT cp
)
1111 CFDataRef ret
= NULL
;
1114 if ((str
= GlobalLock(data
)))
1116 HANDLE unicode
= convert_text(str
, GlobalSize(data
), cp
, -1);
1118 ret
= export_unicodetext_to_utf16(unicode
);
1120 GlobalFree(unicode
);
1128 /**************************************************************************
1131 * Export CF_DIB to BMP file format. This just entails prepending a BMP
1132 * file format header to the data.
1134 static CFDataRef
export_dib_to_bmp(HANDLE data
)
1136 CFMutableDataRef ret
= NULL
;
1139 BITMAPFILEHEADER bfh
;
1141 dibdata
= GlobalLock(data
);
1145 len
= sizeof(bfh
) + GlobalSize(data
);
1146 ret
= CFDataCreateMutable(NULL
, len
);
1149 bfh
.bfType
= 0x4d42; /* "BM" */
1151 bfh
.bfReserved1
= 0;
1152 bfh
.bfReserved2
= 0;
1153 bfh
.bfOffBits
= sizeof(bfh
) + bitmap_info_size((BITMAPINFO
*)dibdata
, DIB_RGB_COLORS
);
1154 CFDataAppendBytes(ret
, (UInt8
*)&bfh
, sizeof(bfh
));
1156 /* rest of bitmap is the same as the packed dib */
1157 CFDataAppendBytes(ret
, (UInt8
*)dibdata
, len
- sizeof(bfh
));
1166 /**************************************************************************
1167 * export_hdrop_to_filenames
1169 * Export CF_HDROP to NSFilenamesPboardType data, which is a CFArray of
1170 * CFStrings (holding Unix paths) which is serialized as a property list.
1172 static CFDataRef
export_hdrop_to_filenames(HANDLE data
)
1174 CFDataRef ret
= NULL
;
1175 DROPFILES
*dropfiles
;
1176 CFMutableArrayRef filenames
= NULL
;
1178 WCHAR
*buffer
= NULL
;
1179 size_t buffer_len
= 0;
1181 TRACE("data %p\n", data
);
1183 if (!(dropfiles
= GlobalLock(data
)))
1185 WARN("failed to lock data %p\n", data
);
1189 filenames
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1192 WARN("failed to create filenames array\n");
1196 p
= (char*)dropfiles
+ dropfiles
->pFiles
;
1197 while (dropfiles
->fWide
? *(WCHAR
*)p
: *(char*)p
)
1200 CFStringRef filename
;
1202 TRACE(" %s\n", dropfiles
->fWide
? debugstr_w(p
) : debugstr_a(p
));
1204 if (dropfiles
->fWide
)
1205 unixname
= wine_get_unix_file_name(p
);
1208 int len
= MultiByteToWideChar(CP_ACP
, 0, p
, -1, NULL
, 0);
1211 if (len
> buffer_len
)
1213 HeapFree(GetProcessHeap(), 0, buffer
);
1214 buffer_len
= len
* 2;
1215 buffer
= HeapAlloc(GetProcessHeap(), 0, buffer_len
* sizeof(*buffer
));
1218 MultiByteToWideChar(CP_ACP
, 0, p
, -1, buffer
, buffer_len
);
1219 unixname
= wine_get_unix_file_name(buffer
);
1226 WARN("failed to convert DOS path to Unix: %s\n",
1227 dropfiles
->fWide
? debugstr_w(p
) : debugstr_a(p
));
1231 if (dropfiles
->fWide
)
1232 p
= (WCHAR
*)p
+ strlenW(p
) + 1;
1234 p
= (char*)p
+ strlen(p
) + 1;
1236 filename
= CFStringCreateWithFileSystemRepresentation(NULL
, unixname
);
1237 HeapFree(GetProcessHeap(), 0, unixname
);
1240 WARN("failed to create CFString from Unix path %s\n", debugstr_a(unixname
));
1244 CFArrayAppendValue(filenames
, filename
);
1245 CFRelease(filename
);
1248 ret
= CFPropertyListCreateData(NULL
, filenames
, kCFPropertyListXMLFormat_v1_0
, 0, NULL
);
1251 HeapFree(GetProcessHeap(), 0, buffer
);
1253 if (filenames
) CFRelease(filenames
);
1254 TRACE(" -> %s\n", debugstr_cf(ret
));
1259 /**************************************************************************
1260 * export_oemtext_to_utf8
1262 * Export CF_OEMTEXT to UTF-8.
1264 static CFDataRef
export_oemtext_to_utf8(HANDLE data
)
1266 return export_codepage_to_utf8(data
, CP_OEMCP
);
1270 /**************************************************************************
1271 * export_oemtext_to_utf16
1273 * Export CF_OEMTEXT to UTF-16.
1275 static CFDataRef
export_oemtext_to_utf16(HANDLE data
)
1277 return export_codepage_to_utf16(data
, CP_OEMCP
);
1281 /**************************************************************************
1282 * export_text_to_utf8
1284 * Export CF_TEXT to UTF-8.
1286 static CFDataRef
export_text_to_utf8(HANDLE data
)
1288 return export_codepage_to_utf8(data
, CP_ACP
);
1292 /**************************************************************************
1293 * export_text_to_utf16
1295 * Export CF_TEXT to UTF-16.
1297 static CFDataRef
export_text_to_utf16(HANDLE data
)
1299 return export_codepage_to_utf16(data
, CP_ACP
);
1303 /**************************************************************************
1304 * export_unicodetext_to_utf8
1306 * Export CF_UNICODETEXT to UTF-8.
1308 static CFDataRef
export_unicodetext_to_utf8(HANDLE data
)
1310 CFMutableDataRef ret
;
1314 src
= GlobalLock(data
);
1315 if (!src
) return NULL
;
1317 dst_len
= WideCharToMultiByte(CP_UTF8
, 0, src
, -1, NULL
, 0, NULL
, NULL
);
1318 if (dst_len
) dst_len
--; /* Leave off null terminator. */
1319 ret
= CFDataCreateMutable(NULL
, dst_len
);
1325 CFDataSetLength(ret
, dst_len
);
1326 dst
= (LPSTR
)CFDataGetMutableBytePtr(ret
);
1327 WideCharToMultiByte(CP_UTF8
, 0, src
, -1, dst
, dst_len
, NULL
, NULL
);
1329 /* Remove carriage returns */
1330 for (i
= 0, j
= 0; i
< dst_len
; i
++)
1332 if (dst
[i
] == '\r' &&
1333 (i
+ 1 >= dst_len
|| dst
[i
+ 1] == '\n' || dst
[i
+ 1] == '\0'))
1337 CFDataSetLength(ret
, j
);
1345 /**************************************************************************
1346 * export_unicodetext_to_utf16
1348 * Export CF_UNICODETEXT to UTF-16.
1350 static CFDataRef
export_unicodetext_to_utf16(HANDLE data
)
1352 CFMutableDataRef ret
;
1356 src
= GlobalLock(data
);
1357 if (!src
) return NULL
;
1359 dst_len
= GlobalSize(data
) / sizeof(WCHAR
);
1360 if (dst_len
) dst_len
--; /* Leave off null terminator. */
1361 ret
= CFDataCreateMutable(NULL
, dst_len
);
1367 CFDataSetLength(ret
, dst_len
);
1368 dst
= (LPWSTR
)CFDataGetMutableBytePtr(ret
);
1370 /* Remove carriage returns */
1371 for (i
= 0, j
= 0; i
< dst_len
; i
++)
1373 if (src
[i
] == '\r' &&
1374 (i
+ 1 >= dst_len
|| src
[i
+ 1] == '\n' || src
[i
+ 1] == '\0'))
1378 CFDataSetLength(ret
, j
);
1386 /**************************************************************************
1387 * get_clipboard_info
1389 static BOOL
get_clipboard_info(LPCLIPBOARDINFO cbinfo
)
1393 SERVER_START_REQ(set_clipboard_info
)
1397 if (wine_server_call_err(req
))
1399 ERR("Failed to get clipboard owner.\n");
1403 cbinfo
->hwnd_owner
= wine_server_ptr_handle(reply
->old_owner
);
1404 cbinfo
->flags
= reply
->flags
;
1415 /**************************************************************************
1418 static BOOL
release_ownership(void)
1422 SERVER_START_REQ(set_clipboard_info
)
1424 req
->flags
= SET_CB_RELOWNER
| SET_CB_SEQNO
;
1426 if (wine_server_call_err(req
))
1427 ERR("Failed to set clipboard.\n");
1437 /**************************************************************************
1438 * macdrv_get_pasteboard_data
1440 HANDLE
macdrv_get_pasteboard_data(CFTypeRef pasteboard
, UINT desired_format
)
1445 CFStringRef type
, best_type
;
1446 WINE_CLIPFORMAT
* best_format
= NULL
;
1449 TRACE("pasteboard %p, desired_format %s\n", pasteboard
, debugstr_format(desired_format
));
1451 types
= macdrv_copy_pasteboard_types(pasteboard
);
1454 WARN("Failed to copy pasteboard types\n");
1458 count
= CFArrayGetCount(types
);
1459 TRACE("got %ld types\n", count
);
1461 for (i
= 0; (!best_format
|| best_format
->synthesized
) && i
< count
; i
++)
1463 WINE_CLIPFORMAT
* format
;
1465 type
= CFArrayGetValueAtIndex(types
, i
);
1468 while ((!best_format
|| best_format
->synthesized
) && (format
= format_for_type(format
, type
)))
1470 TRACE("for type %s got format %p/%s\n", debugstr_cf(type
), format
, debugstr_format(format
? format
->format_id
: 0));
1472 if (format
->format_id
== desired_format
)
1474 /* The best format is the matching one which is not synthesized. Failing that,
1475 the best format is the first matching synthesized format. */
1476 if (!format
->synthesized
|| !best_format
)
1479 best_format
= format
;
1487 CFDataRef pasteboard_data
= macdrv_copy_pasteboard_data(pasteboard
, best_type
);
1489 TRACE("got pasteboard data for type %s: %s\n", debugstr_cf(best_type
), debugstr_cf(pasteboard_data
));
1491 if (pasteboard_data
)
1493 data
= best_format
->import_func(pasteboard_data
);
1494 CFRelease(pasteboard_data
);
1499 TRACE(" -> %p\n", data
);
1504 /**************************************************************************
1505 * macdrv_pasteboard_has_format
1507 BOOL
macdrv_pasteboard_has_format(CFTypeRef pasteboard
, UINT desired_format
)
1514 TRACE("pasteboard %p, desired_format %s\n", pasteboard
, debugstr_format(desired_format
));
1516 types
= macdrv_copy_pasteboard_types(pasteboard
);
1519 WARN("Failed to copy pasteboard types\n");
1523 count
= CFArrayGetCount(types
);
1524 TRACE("got %d types\n", count
);
1526 for (i
= 0; !found
&& i
< count
; i
++)
1528 CFStringRef type
= CFArrayGetValueAtIndex(types
, i
);
1529 WINE_CLIPFORMAT
* format
;
1532 while (!found
&& (format
= format_for_type(format
, type
)))
1534 TRACE("for type %s got format %s\n", debugstr_cf(type
), debugstr_format(format
->format_id
));
1536 if (format
->format_id
== desired_format
)
1542 TRACE(" -> %d\n", found
);
1547 /**************************************************************************
1548 * macdrv_copy_pasteboard_formats
1550 CFArrayRef
macdrv_copy_pasteboard_formats(CFTypeRef pasteboard
)
1554 CFMutableArrayRef formats
;
1557 TRACE("pasteboard %p\n", pasteboard
);
1559 types
= macdrv_copy_pasteboard_types(pasteboard
);
1562 WARN("Failed to copy pasteboard types\n");
1566 count
= CFArrayGetCount(types
);
1567 TRACE("got %ld types\n", count
);
1575 formats
= CFArrayCreateMutable(NULL
, 0, NULL
);
1578 WARN("Failed to allocate formats array\n");
1583 for (i
= 0; i
< count
; i
++)
1585 CFStringRef type
= CFArrayGetValueAtIndex(types
, i
);
1586 WINE_CLIPFORMAT
* format
;
1589 while ((format
= format_for_type(format
, type
)))
1591 TRACE("for type %s got format %p/%s\n", debugstr_cf(type
), format
, debugstr_format(format
->format_id
));
1593 if (format
->synthesized
)
1595 /* Don't override a real value with a synthesized value. */
1596 if (!CFArrayContainsValue(formats
, CFRangeMake(0, CFArrayGetCount(formats
)), (void*)format
->format_id
))
1597 CFArrayAppendValue(formats
, (void*)format
->format_id
);
1601 /* If the type was already in the array, it must have been synthesized
1602 because this one's real. Remove the synthesized entry in favor of
1604 CFIndex index
= CFArrayGetFirstIndexOfValue(formats
, CFRangeMake(0, CFArrayGetCount(formats
)),
1605 (void*)format
->format_id
);
1606 if (index
!= kCFNotFound
)
1607 CFArrayRemoveValueAtIndex(formats
, index
);
1608 CFArrayAppendValue(formats
, (void*)format
->format_id
);
1615 TRACE(" -> %s\n", debugstr_cf(formats
));
1620 /**************************************************************************
1621 * check_clipboard_ownership
1623 static void check_clipboard_ownership(HWND
*owner
)
1625 CLIPBOARDINFO cbinfo
;
1627 if (owner
) *owner
= NULL
;
1629 /* If Wine thinks we're the clipboard owner but Mac OS X thinks we're not
1630 the pasteboard owner, update Wine. */
1631 if (get_clipboard_info(&cbinfo
) && (cbinfo
.flags
& CB_PROCESS
))
1633 if (!(cbinfo
.flags
& CB_OPEN
) && !macdrv_is_pasteboard_owner())
1635 TRACE("Lost clipboard ownership\n");
1637 if (OpenClipboard(cbinfo
.hwnd_owner
))
1639 /* Destroy private objects */
1640 SendMessageW(cbinfo
.hwnd_owner
, WM_DESTROYCLIPBOARD
, 0, 0);
1642 /* Give up ownership of the windows clipboard */
1643 release_ownership();
1648 *owner
= cbinfo
.hwnd_owner
;
1653 /**************************************************************************
1654 * Mac User Driver Clipboard Exports
1655 **************************************************************************/
1658 /**************************************************************************
1659 * AcquireClipboard (MACDRV.@)
1661 int CDECL
macdrv_AcquireClipboard(HWND hwnd
)
1663 TRACE("hwnd %p\n", hwnd
);
1664 check_clipboard_ownership(NULL
);
1669 /**************************************************************************
1670 * CountClipboardFormats (MACDRV.@)
1672 INT CDECL
macdrv_CountClipboardFormats(void)
1674 CFMutableSetRef seen_formats
;
1681 check_clipboard_ownership(NULL
);
1683 seen_formats
= CFSetCreateMutable(NULL
, 0, NULL
);
1686 WARN("Failed to allocate set to track seen formats\n");
1690 types
= macdrv_copy_pasteboard_types(NULL
);
1693 WARN("Failed to copy pasteboard types\n");
1694 CFRelease(seen_formats
);
1698 count
= CFArrayGetCount(types
);
1699 TRACE("got %ld types\n", count
);
1701 for (i
= 0; i
< count
; i
++)
1703 CFStringRef type
= CFArrayGetValueAtIndex(types
, i
);
1704 WINE_CLIPFORMAT
* format
;
1707 while ((format
= format_for_type(format
, type
)))
1709 TRACE("for type %s got format %p/%s\n", debugstr_cf(type
), format
, debugstr_format(format
->format_id
));
1711 if (!CFSetContainsValue(seen_formats
, (void*)format
->format_id
))
1714 CFSetAddValue(seen_formats
, (void*)format
->format_id
);
1719 CFRelease(seen_formats
);
1720 TRACE(" -> %d\n", ret
);
1725 /**************************************************************************
1726 * EmptyClipboard (MACDRV.@)
1728 * Empty cached clipboard data.
1730 void CDECL
macdrv_EmptyClipboard(BOOL keepunowned
)
1732 TRACE("keepunowned %d\n", keepunowned
);
1733 macdrv_clear_pasteboard();
1737 /**************************************************************************
1738 * EndClipboardUpdate (MACDRV.@)
1740 void CDECL
macdrv_EndClipboardUpdate(void)
1743 check_clipboard_ownership(NULL
);
1747 /**************************************************************************
1748 * EnumClipboardFormats (MACDRV.@)
1750 UINT CDECL
macdrv_EnumClipboardFormats(UINT prev_format
)
1756 TRACE("prev_format %s\n", debugstr_format(prev_format
));
1757 check_clipboard_ownership(NULL
);
1761 CFArrayRef formats
= macdrv_copy_pasteboard_formats(NULL
);
1764 count
= CFArrayGetCount(formats
);
1765 i
= CFArrayGetFirstIndexOfValue(formats
, CFRangeMake(0, count
), (void*)prev_format
);
1766 if (i
!= kCFNotFound
&& i
+ 1 < count
)
1767 ret
= (UINT
)CFArrayGetValueAtIndex(formats
, i
+ 1);
1774 CFArrayRef types
= macdrv_copy_pasteboard_types(NULL
);
1777 count
= CFArrayGetCount(types
);
1778 TRACE("got %ld types\n", count
);
1782 CFStringRef type
= CFArrayGetValueAtIndex(types
, 0);
1783 WINE_CLIPFORMAT
*format
= format_for_type(NULL
, type
);
1785 ret
= format
? format
->format_id
: 0;
1791 WARN("Failed to copy pasteboard types\n");
1794 TRACE(" -> %u\n", ret
);
1799 /**************************************************************************
1800 * GetClipboardData (MACDRV.@)
1802 HANDLE CDECL
macdrv_GetClipboardData(UINT desired_format
)
1804 check_clipboard_ownership(NULL
);
1806 return macdrv_get_pasteboard_data(NULL
, desired_format
);
1810 /**************************************************************************
1811 * IsClipboardFormatAvailable (MACDRV.@)
1813 BOOL CDECL
macdrv_IsClipboardFormatAvailable(UINT desired_format
)
1815 check_clipboard_ownership(NULL
);
1816 return macdrv_pasteboard_has_format(NULL
, desired_format
);
1820 /**************************************************************************
1821 * SetClipboardData (MACDRV.@)
1823 BOOL CDECL
macdrv_SetClipboardData(UINT format_id
, HANDLE data
, BOOL owner
)
1826 macdrv_window window
;
1827 WINE_CLIPFORMAT
*format
;
1828 CFDataRef cfdata
= NULL
;
1830 check_clipboard_ownership(&hwnd_owner
);
1831 window
= macdrv_get_cocoa_window(GetAncestor(hwnd_owner
, GA_ROOT
), FALSE
);
1832 TRACE("format_id %s data %p owner %d hwnd_owner %p window %p)\n", debugstr_format(format_id
), data
, owner
, hwnd_owner
, window
);
1834 /* Find the "natural" format for this format_id (the one which isn't
1835 synthesized from another type). */
1836 LIST_FOR_EACH_ENTRY(format
, &format_list
, WINE_CLIPFORMAT
, entry
)
1837 if (format
->format_id
== format_id
&& !format
->synthesized
) break;
1839 if (&format
->entry
== &format_list
&& !(format
= insert_clipboard_format(format_id
, NULL
)))
1841 WARN("Failed to register clipboard format %s\n", debugstr_format(format_id
));
1845 /* Export the data to the Mac pasteboard. */
1848 if (!format
->export_func
|| !(cfdata
= format
->export_func(data
)))
1850 WARN("Failed to export %s data to type %s\n", debugstr_format(format_id
), debugstr_cf(format
->type
));
1855 if (macdrv_set_pasteboard_data(format
->type
, cfdata
, window
))
1856 TRACE("Set pasteboard data for type %s: %s\n", debugstr_cf(format
->type
), debugstr_cf(cfdata
));
1859 WARN("Failed to set pasteboard data for type %s: %s\n", debugstr_cf(format
->type
), debugstr_cf(cfdata
));
1860 if (cfdata
) CFRelease(cfdata
);
1864 if (cfdata
) CFRelease(cfdata
);
1866 /* Find any other formats for this format_id (the exportable synthesized ones). */
1867 LIST_FOR_EACH_ENTRY(format
, &format_list
, WINE_CLIPFORMAT
, entry
)
1869 if (format
->format_id
== format_id
&& format
->synthesized
&& format
->export_func
)
1871 /* We have a synthesized format for this format ID. Add its type to the pasteboard. */
1872 TRACE("Synthesized from format %s: type %s\n", debugstr_format(format_id
), debugstr_cf(format
->type
));
1876 cfdata
= format
->export_func(data
);
1879 WARN("Failed to export %s data to type %s\n", debugstr_format(format
->format_id
), debugstr_cf(format
->type
));
1886 if (macdrv_set_pasteboard_data(format
->type
, cfdata
, window
))
1887 TRACE(" ... set pasteboard data: %s\n", debugstr_cf(cfdata
));
1889 WARN(" ... failed to set pasteboard data: %s\n", debugstr_cf(cfdata
));
1891 if (cfdata
) CFRelease(cfdata
);
1897 /* FIXME: According to MSDN, the caller is entitled to lock and read from
1898 data until CloseClipboard is called. So, we should defer this cleanup. */
1899 if ((format_id
>= CF_GDIOBJFIRST
&& format_id
<= CF_GDIOBJLAST
) ||
1900 format_id
== CF_BITMAP
||
1901 format_id
== CF_DIB
||
1902 format_id
== CF_PALETTE
)
1906 else if (format_id
== CF_METAFILEPICT
)
1908 DeleteMetaFile(((METAFILEPICT
*)GlobalLock(data
))->hMF
);
1911 else if (format_id
== CF_ENHMETAFILE
)
1913 DeleteEnhMetaFile(data
);
1915 else if (format_id
< CF_PRIVATEFIRST
|| CF_PRIVATELAST
< format_id
)
1925 /**************************************************************************
1926 * MACDRV Private Clipboard Exports
1927 **************************************************************************/
1930 /**************************************************************************
1931 * macdrv_clipboard_process_attach
1933 void macdrv_clipboard_process_attach(void)
1936 WINE_CLIPFORMAT
*format
;
1938 /* Register built-in formats */
1939 for (i
= 0; i
< sizeof(builtin_format_ids
)/sizeof(builtin_format_ids
[0]); i
++)
1941 if (!(format
= HeapAlloc(GetProcessHeap(), 0, sizeof(*format
)))) break;
1942 format
->format_id
= builtin_format_ids
[i
].id
;
1943 format
->type
= CFRetain(builtin_format_ids
[i
].type
);
1944 format
->import_func
= builtin_format_ids
[i
].import
;
1945 format
->export_func
= builtin_format_ids
[i
].export
;
1946 format
->synthesized
= builtin_format_ids
[i
].synthesized
;
1947 list_add_tail(&format_list
, &format
->entry
);
1950 /* Register known mappings between Windows formats and Mac types */
1951 for (i
= 0; i
< sizeof(builtin_format_names
)/sizeof(builtin_format_names
[0]); i
++)
1953 if (!(format
= HeapAlloc(GetProcessHeap(), 0, sizeof(*format
)))) break;
1954 format
->format_id
= RegisterClipboardFormatW(builtin_format_names
[i
].name
);
1955 format
->type
= CFRetain(builtin_format_names
[i
].type
);
1956 format
->import_func
= builtin_format_names
[i
].import
;
1957 format
->export_func
= builtin_format_names
[i
].export
;
1958 format
->synthesized
= FALSE
;
1959 list_add_tail(&format_list
, &format
->entry
);
1964 /**************************************************************************
1965 * query_pasteboard_data
1967 BOOL
query_pasteboard_data(HWND hwnd
, CFStringRef type
)
1970 CLIPBOARDINFO cbinfo
;
1971 WINE_CLIPFORMAT
* format
;
1972 CFArrayRef types
= NULL
;
1975 TRACE("hwnd %p type %s\n", hwnd
, debugstr_cf(type
));
1977 if (get_clipboard_info(&cbinfo
))
1978 hwnd
= cbinfo
.hwnd_owner
;
1981 while ((format
= format_for_type(format
, type
)))
1983 WINE_CLIPFORMAT
* base_format
;
1985 TRACE("for type %s got format %p/%s\n", debugstr_cf(type
), format
, debugstr_format(format
->format_id
));
1987 if (!format
->synthesized
)
1989 TRACE("Sending WM_RENDERFORMAT message for format %s to hwnd %p\n", debugstr_format(format
->format_id
), hwnd
);
1990 SendMessageW(hwnd
, WM_RENDERFORMAT
, format
->format_id
, 0);
1997 types
= macdrv_copy_pasteboard_types(NULL
);
2000 WARN("Failed to copy pasteboard types\n");
2004 range
= CFRangeMake(0, CFArrayGetCount(types
));
2007 /* The type maps to a synthesized format. Now look up what type that format maps to natively
2008 (not synthesized). For example, if type is "public.utf8-plain-text", then this format may
2009 have an ID of CF_TEXT. From CF_TEXT, we want to find "org.winehq.builtin.text" to see if
2010 that type is present in the pasteboard. If it is, then the app must have promised it and
2011 we can ask it to render it. (If it had put it on the clipboard immediately, then the
2012 pasteboard would also have data for "public.utf8-plain-text" and we wouldn't be here.) If
2013 "org.winehq.builtin.text" is not on the pasteboard, then one of the other text formats is
2014 presumably responsible for the promise that we're trying to satisfy, so we keep looking. */
2015 LIST_FOR_EACH_ENTRY(base_format
, &format_list
, WINE_CLIPFORMAT
, entry
)
2017 if (base_format
->format_id
== format
->format_id
&& !base_format
->synthesized
&&
2018 CFArrayContainsValue(types
, range
, base_format
->type
))
2020 TRACE("Sending WM_RENDERFORMAT message for format %s to hwnd %p\n", debugstr_format(base_format
->format_id
), hwnd
);
2021 SendMessageW(hwnd
, WM_RENDERFORMAT
, base_format
->format_id
, 0);
2029 if (types
) CFRelease(types
);