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
))
372 if (CFStringHasPrefix(type
, CFSTR("org.winehq.builtin.")))
374 ERR("Shouldn't happen. Built-in type %s should have matched something in format list.\n",
378 else if (CFStringHasPrefix(type
, registered_name_type_prefix
))
380 int len
= CFStringGetLength(type
) - CFStringGetLength(registered_name_type_prefix
);
381 name
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
));
382 CFStringGetCharacters(type
, CFRangeMake(CFStringGetLength(registered_name_type_prefix
), len
),
388 int len
= strlenW(mac_type_name_prefix
) + CFStringGetLength(type
);
389 name
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
));
390 memcpy(name
, mac_type_name_prefix
, sizeof(mac_type_name_prefix
));
391 CFStringGetCharacters(type
, CFRangeMake(0, CFStringGetLength(type
)),
392 (UniChar
*)name
+ strlenW(mac_type_name_prefix
));
396 format
= register_format(RegisterClipboardFormatW(name
), type
);
398 ERR("Failed to register format for type %s name %s\n", debugstr_cf(type
), debugstr_w(name
));
400 HeapFree(GetProcessHeap(), 0, name
);
404 TRACE(" -> %p/%s\n", format
, debugstr_format(format
? format
->format_id
: 0));
409 /**************************************************************************
412 * Convert string data between code pages or to/from wide characters. The
413 * special value of (UINT)-1 for a code page indicates to use wide
416 static HANDLE
convert_text(const void *src
, int src_len
, UINT src_cp
, UINT dest_cp
)
424 if (src_cp
== (UINT
)-1)
427 wstr_len
= src_len
/ sizeof(WCHAR
);
433 wstr_len
= MultiByteToWideChar(src_cp
, 0, src
, src_len
, NULL
, 0);
434 if (!src_len
|| ((const char*)src
)[src_len
- 1]) wstr_len
+= 1;
435 temp
= HeapAlloc(GetProcessHeap(), 0, wstr_len
* sizeof(WCHAR
));
436 MultiByteToWideChar(src_cp
, 0, src
, src_len
, temp
, wstr_len
);
437 temp
[wstr_len
- 1] = 0;
441 if (dest_cp
== (UINT
)-1)
443 handle
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, wstr_len
* sizeof(WCHAR
));
444 if (handle
&& (p
= GlobalLock(handle
)))
446 memcpy(p
, wstr
, wstr_len
* sizeof(WCHAR
));
447 GlobalUnlock(handle
);
455 len
= WideCharToMultiByte(dest_cp
, 0, wstr
, wstr_len
, NULL
, 0, NULL
, NULL
);
456 if (!wstr_len
|| wstr
[wstr_len
- 1]) len
+= 1;
457 handle
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, len
);
459 if (handle
&& (p
= GlobalLock(handle
)))
461 WideCharToMultiByte(dest_cp
, 0, wstr
, wstr_len
, p
, len
, NULL
, NULL
);
463 GlobalUnlock(handle
);
472 /**************************************************************************
473 * convert_unicodetext_to_codepage
475 static HANDLE
convert_unicodetext_to_codepage(HANDLE unicode_handle
, UINT cp
)
477 LPWSTR unicode_string
= GlobalLock(unicode_handle
);
482 ret
= convert_text(unicode_string
, GlobalSize(unicode_handle
), -1, cp
);
483 GlobalUnlock(unicode_handle
);
490 /***********************************************************************
493 * Return the size of the bitmap info structure including color table.
495 static int bitmap_info_size(const BITMAPINFO
*info
, WORD coloruse
)
497 unsigned int colors
, size
, masks
= 0;
499 if (info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
501 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)info
;
502 colors
= (core
->bcBitCount
<= 8) ? 1 << core
->bcBitCount
: 0;
503 return sizeof(BITMAPCOREHEADER
) + colors
*
504 ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBTRIPLE
) : sizeof(WORD
));
506 else /* assume BITMAPINFOHEADER */
508 colors
= info
->bmiHeader
.biClrUsed
;
509 if (!colors
&& (info
->bmiHeader
.biBitCount
<= 8))
510 colors
= 1 << info
->bmiHeader
.biBitCount
;
511 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
) masks
= 3;
512 size
= max(info
->bmiHeader
.biSize
, sizeof(BITMAPINFOHEADER
) + masks
* sizeof(DWORD
));
513 return size
+ colors
* ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBQUAD
) : sizeof(WORD
));
518 /***********************************************************************
519 * create_dib_from_bitmap
521 * Allocates a packed DIB and copies the bitmap data into it.
523 static HGLOBAL
create_dib_from_bitmap(HBITMAP hBmp
)
529 LPBITMAPINFOHEADER pbmiHeader
;
530 unsigned int cDataSize
, cPackedSize
, OffsetBits
;
533 if (!GetObjectW(hBmp
, sizeof(bmp
), &bmp
)) return 0;
536 * A packed DIB contains a BITMAPINFO structure followed immediately by
537 * an optional color palette and the pixel data.
540 /* Calculate the size of the packed DIB */
541 cDataSize
= abs(bmp
.bmHeight
) * (((bmp
.bmWidth
* bmp
.bmBitsPixel
+ 31) / 8) & ~3);
542 cPackedSize
= sizeof(BITMAPINFOHEADER
)
543 + ((bmp
.bmBitsPixel
<= 8) ? (sizeof(RGBQUAD
) * (1 << bmp
.bmBitsPixel
)) : 0)
545 /* Get the offset to the bits */
546 OffsetBits
= cPackedSize
- cDataSize
;
548 /* Allocate the packed DIB */
549 TRACE("\tAllocating packed DIB of size %d\n", cPackedSize
);
550 hPackedDIB
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, cPackedSize
);
553 WARN("Could not allocate packed DIB!\n");
557 /* A packed DIB starts with a BITMAPINFOHEADER */
558 pPackedDIB
= GlobalLock(hPackedDIB
);
559 pbmiHeader
= (LPBITMAPINFOHEADER
)pPackedDIB
;
561 /* Init the BITMAPINFOHEADER */
562 pbmiHeader
->biSize
= sizeof(BITMAPINFOHEADER
);
563 pbmiHeader
->biWidth
= bmp
.bmWidth
;
564 pbmiHeader
->biHeight
= bmp
.bmHeight
;
565 pbmiHeader
->biPlanes
= 1;
566 pbmiHeader
->biBitCount
= bmp
.bmBitsPixel
;
567 pbmiHeader
->biCompression
= BI_RGB
;
568 pbmiHeader
->biSizeImage
= 0;
569 pbmiHeader
->biXPelsPerMeter
= pbmiHeader
->biYPelsPerMeter
= 0;
570 pbmiHeader
->biClrUsed
= 0;
571 pbmiHeader
->biClrImportant
= 0;
573 /* Retrieve the DIB bits from the bitmap and fill in the
574 * DIB color table if present */
576 nLinesCopied
= GetDIBits(hdc
, /* Handle to device context */
577 hBmp
, /* Handle to bitmap */
578 0, /* First scan line to set in dest bitmap */
579 bmp
.bmHeight
, /* Number of scan lines to copy */
580 pPackedDIB
+ OffsetBits
, /* [out] Address of array for bitmap bits */
581 (LPBITMAPINFO
) pbmiHeader
, /* [out] Address of BITMAPINFO structure */
582 0); /* RGB or palette index */
583 GlobalUnlock(hPackedDIB
);
586 /* Cleanup if GetDIBits failed */
587 if (nLinesCopied
!= bmp
.bmHeight
)
589 TRACE("\tGetDIBits returned %d. Actual lines=%d\n", nLinesCopied
, bmp
.bmHeight
);
590 GlobalFree(hPackedDIB
);
597 /**************************************************************************
598 * import_clipboard_data
600 * Generic import clipboard data routine.
602 static HANDLE
import_clipboard_data(CFDataRef data
)
604 HANDLE data_handle
= NULL
;
606 size_t len
= CFDataGetLength(data
);
611 /* Turn on the DDESHARE flag to enable shared 32 bit memory */
612 data_handle
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, len
);
616 if ((p
= GlobalLock(data_handle
)))
618 memcpy(p
, CFDataGetBytePtr(data
), len
);
619 GlobalUnlock(data_handle
);
623 GlobalFree(data_handle
);
632 /**************************************************************************
633 * import_bmp_to_bitmap
635 * Import BMP data, converting to CF_BITMAP format.
637 static HANDLE
import_bmp_to_bitmap(CFDataRef data
)
640 HANDLE dib
= import_bmp_to_dib(data
);
643 if (dib
&& (bmi
= GlobalLock(dib
)))
650 offset
= bitmap_info_size(bmi
, DIB_RGB_COLORS
);
652 ret
= CreateDIBitmap(hdc
, &bmi
->bmiHeader
, CBM_INIT
, (LPBYTE
)bmi
+ offset
,
653 bmi
, DIB_RGB_COLORS
);
656 ReleaseDC(NULL
, hdc
);
664 /**************************************************************************
667 * Import BMP data, converting to CF_DIB format. This just entails
668 * stripping the BMP file format header.
670 static HANDLE
import_bmp_to_dib(CFDataRef data
)
673 BITMAPFILEHEADER
*bfh
= (BITMAPFILEHEADER
*)CFDataGetBytePtr(data
);
674 CFIndex len
= CFDataGetLength(data
);
676 if (len
>= sizeof(*bfh
) + sizeof(BITMAPCOREHEADER
) &&
677 bfh
->bfType
== 0x4d42 /* "BM" */)
679 BITMAPINFO
*bmi
= (BITMAPINFO
*)(bfh
+ 1);
683 ret
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, len
);
684 if (!ret
|| !(p
= GlobalLock(ret
)))
698 /**************************************************************************
699 * import_nsfilenames_to_hdrop
701 * Import NSFilenamesPboardType data, converting the property-list-
702 * serialized array of path strings to CF_HDROP.
704 static HANDLE
import_nsfilenames_to_hdrop(CFDataRef data
)
711 WCHAR
**paths
= NULL
;
712 DROPFILES
* dropfiles
;
715 TRACE("data %s\n", debugstr_cf(data
));
717 names
= (CFArrayRef
)CFPropertyListCreateWithData(NULL
, data
, kCFPropertyListImmutable
,
719 if (!names
|| CFGetTypeID(names
) != CFArrayGetTypeID())
721 WARN("failed to interpret data as a CFArray\n");
725 count
= CFArrayGetCount(names
);
728 for (i
= 0; i
< count
; i
++)
731 CFStringRef name
= (CFStringRef
)CFArrayGetValueAtIndex(names
, i
);
732 TRACE(" %s\n", debugstr_cf(name
));
733 if (CFGetTypeID(name
) != CFStringGetTypeID())
735 WARN("non-string in array\n");
739 this_len
= CFStringGetMaximumSizeOfFileSystemRepresentation(name
);
744 buffer
= HeapAlloc(GetProcessHeap(), 0, len
);
747 WARN("failed to allocate buffer for file-system representations\n");
751 paths
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, count
* sizeof(paths
[0]));
754 WARN("failed to allocate array of DOS paths\n");
758 for (i
= 0; i
< count
; i
++)
760 CFStringRef name
= (CFStringRef
)CFArrayGetValueAtIndex(names
, i
);
761 if (!CFStringGetFileSystemRepresentation(name
, buffer
, len
))
763 WARN("failed to get file-system representation for %s\n", debugstr_cf(name
));
766 paths
[i
] = wine_get_dos_file_name(buffer
);
769 WARN("failed to get DOS path for %s\n", debugstr_a(buffer
));
774 len
= 1; /* for the terminating null */
775 for (i
= 0; i
< count
; i
++)
776 len
+= strlenW(paths
[i
]) + 1;
778 hdrop
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, sizeof(*dropfiles
) + len
* sizeof(WCHAR
));
779 if (!hdrop
|| !(dropfiles
= GlobalLock(hdrop
)))
781 WARN("failed to allocate HDROP\n");
787 dropfiles
->pFiles
= sizeof(*dropfiles
);
790 dropfiles
->fNC
= FALSE
;
791 dropfiles
->fWide
= TRUE
;
793 p
= (WCHAR
*)(dropfiles
+ 1);
794 for (i
= 0; i
< count
; i
++)
796 strcpyW(p
, paths
[i
]);
806 for (i
= 0; i
< count
; i
++)
807 HeapFree(GetProcessHeap(), 0, paths
[i
]);
808 HeapFree(GetProcessHeap(), 0, paths
);
810 HeapFree(GetProcessHeap(), 0, buffer
);
811 if (names
) CFRelease(names
);
816 /**************************************************************************
817 * import_oemtext_to_text
819 * Import CF_OEMTEXT data, converting the string to CF_TEXT.
821 static HANDLE
import_oemtext_to_text(CFDataRef data
)
823 return convert_text(CFDataGetBytePtr(data
), CFDataGetLength(data
), CP_OEMCP
, CP_ACP
);
827 /**************************************************************************
828 * import_oemtext_to_unicodetext
830 * Import CF_OEMTEXT data, converting the string to CF_UNICODETEXT.
832 static HANDLE
import_oemtext_to_unicodetext(CFDataRef data
)
834 return convert_text(CFDataGetBytePtr(data
), CFDataGetLength(data
), CP_OEMCP
, -1);
838 /**************************************************************************
839 * import_text_to_oemtext
841 * Import CF_TEXT data, converting the string to CF_OEMTEXT.
843 static HANDLE
import_text_to_oemtext(CFDataRef data
)
845 return convert_text(CFDataGetBytePtr(data
), CFDataGetLength(data
), CP_ACP
, CP_OEMCP
);
849 /**************************************************************************
850 * import_text_to_unicodetext
852 * Import CF_TEXT data, converting the string to CF_UNICODETEXT.
854 static HANDLE
import_text_to_unicodetext(CFDataRef data
)
856 return convert_text(CFDataGetBytePtr(data
), CFDataGetLength(data
), CP_ACP
, -1);
860 /**************************************************************************
861 * import_unicodetext_to_oemtext
863 * Import a CF_UNICODETEXT string, converting the string to CF_OEMTEXT.
865 static HANDLE
import_unicodetext_to_oemtext(CFDataRef data
)
867 return convert_text(CFDataGetBytePtr(data
), CFDataGetLength(data
), -1, CP_OEMCP
);
871 /**************************************************************************
872 * import_unicodetext_to_text
874 * Import a CF_UNICODETEXT string, converting the string to CF_TEXT.
876 static HANDLE
import_unicodetext_to_text(CFDataRef data
)
878 return convert_text(CFDataGetBytePtr(data
), CFDataGetLength(data
), -1, CP_ACP
);
882 /**************************************************************************
883 * import_utf8_to_oemtext
885 * Import a UTF-8 string, converting the string to CF_OEMTEXT.
887 static HANDLE
import_utf8_to_oemtext(CFDataRef data
)
889 HANDLE unicode_handle
= import_utf8_to_unicodetext(data
);
890 HANDLE ret
= convert_unicodetext_to_codepage(unicode_handle
, CP_OEMCP
);
892 GlobalFree(unicode_handle
);
897 /**************************************************************************
898 * import_utf8_to_text
900 * Import a UTF-8 string, converting the string to CF_TEXT.
902 static HANDLE
import_utf8_to_text(CFDataRef data
)
904 HANDLE unicode_handle
= import_utf8_to_unicodetext(data
);
905 HANDLE ret
= convert_unicodetext_to_codepage(unicode_handle
, CP_ACP
);
907 GlobalFree(unicode_handle
);
912 /**************************************************************************
913 * import_utf8_to_unicodetext
915 * Import a UTF-8 string, converting the string to CF_UNICODETEXT.
917 static HANDLE
import_utf8_to_unicodetext(CFDataRef data
)
920 unsigned long src_len
;
921 unsigned long new_lines
= 0;
924 HANDLE unicode_handle
= NULL
;
926 src
= CFDataGetBytePtr(data
);
927 src_len
= CFDataGetLength(data
);
928 for (i
= 0; i
< src_len
; i
++)
934 if ((dst
= HeapAlloc(GetProcessHeap(), 0, src_len
+ new_lines
+ 1)))
938 for (i
= 0, j
= 0; i
< src_len
; i
++)
947 count
= MultiByteToWideChar(CP_UTF8
, 0, dst
, -1, NULL
, 0);
948 unicode_handle
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, count
* sizeof(WCHAR
));
952 WCHAR
*textW
= GlobalLock(unicode_handle
);
953 MultiByteToWideChar(CP_UTF8
, 0, dst
, -1, textW
, count
);
954 GlobalUnlock(unicode_handle
);
957 HeapFree(GetProcessHeap(), 0, dst
);
960 return unicode_handle
;
964 /**************************************************************************
965 * import_utf16_to_oemtext
967 * Import a UTF-16 string, converting the string to CF_OEMTEXT.
969 static HANDLE
import_utf16_to_oemtext(CFDataRef data
)
971 HANDLE unicode_handle
= import_utf16_to_unicodetext(data
);
972 HANDLE ret
= convert_unicodetext_to_codepage(unicode_handle
, CP_OEMCP
);
974 GlobalFree(unicode_handle
);
979 /**************************************************************************
980 * import_utf16_to_text
982 * Import a UTF-16 string, converting the string to CF_TEXT.
984 static HANDLE
import_utf16_to_text(CFDataRef data
)
986 HANDLE unicode_handle
= import_utf16_to_unicodetext(data
);
987 HANDLE ret
= convert_unicodetext_to_codepage(unicode_handle
, CP_ACP
);
989 GlobalFree(unicode_handle
);
994 /**************************************************************************
995 * import_utf16_to_unicodetext
997 * Import a UTF-8 string, converting the string to CF_UNICODETEXT.
999 static HANDLE
import_utf16_to_unicodetext(CFDataRef data
)
1002 unsigned long src_len
;
1003 unsigned long new_lines
= 0;
1006 HANDLE unicode_handle
;
1008 src
= (const WCHAR
*)CFDataGetBytePtr(data
);
1009 src_len
= CFDataGetLength(data
) / sizeof(WCHAR
);
1010 for (i
= 0; i
< src_len
; i
++)
1016 if ((unicode_handle
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, (src_len
+ new_lines
+ 1) * sizeof(WCHAR
))))
1018 dst
= GlobalLock(unicode_handle
);
1020 for (i
= 0, j
= 0; i
< src_len
; i
++)
1029 GlobalUnlock(unicode_handle
);
1032 return unicode_handle
;
1036 /**************************************************************************
1037 * export_clipboard_data
1039 * Generic export clipboard data routine.
1041 static CFDataRef
export_clipboard_data(HANDLE data
)
1047 len
= GlobalSize(data
);
1048 src
= GlobalLock(data
);
1049 if (!src
) return NULL
;
1051 ret
= CFDataCreate(NULL
, src
, len
);
1058 /**************************************************************************
1059 * export_bitmap_to_bmp
1061 * Export CF_BITMAP to BMP file format.
1063 static CFDataRef
export_bitmap_to_bmp(HANDLE data
)
1065 CFDataRef ret
= NULL
;
1068 dib
= create_dib_from_bitmap(data
);
1071 ret
= export_dib_to_bmp(dib
);
1079 /**************************************************************************
1080 * export_codepage_to_utf8
1082 * Export string data in a specified codepage to UTF-8.
1084 static CFDataRef
export_codepage_to_utf8(HANDLE data
, UINT cp
)
1086 CFDataRef ret
= NULL
;
1089 if ((str
= GlobalLock(data
)))
1091 HANDLE unicode
= convert_text(str
, GlobalSize(data
), cp
, -1);
1093 ret
= export_unicodetext_to_utf8(unicode
);
1095 GlobalFree(unicode
);
1103 /**************************************************************************
1104 * export_codepage_to_utf16
1106 * Export string data in a specified codepage to UTF-16.
1108 static CFDataRef
export_codepage_to_utf16(HANDLE data
, UINT cp
)
1110 CFDataRef ret
= NULL
;
1113 if ((str
= GlobalLock(data
)))
1115 HANDLE unicode
= convert_text(str
, GlobalSize(data
), cp
, -1);
1117 ret
= export_unicodetext_to_utf16(unicode
);
1119 GlobalFree(unicode
);
1127 /**************************************************************************
1130 * Export CF_DIB to BMP file format. This just entails prepending a BMP
1131 * file format header to the data.
1133 static CFDataRef
export_dib_to_bmp(HANDLE data
)
1135 CFMutableDataRef ret
= NULL
;
1138 BITMAPFILEHEADER bfh
;
1140 dibdata
= GlobalLock(data
);
1144 len
= sizeof(bfh
) + GlobalSize(data
);
1145 ret
= CFDataCreateMutable(NULL
, len
);
1148 bfh
.bfType
= 0x4d42; /* "BM" */
1150 bfh
.bfReserved1
= 0;
1151 bfh
.bfReserved2
= 0;
1152 bfh
.bfOffBits
= sizeof(bfh
) + bitmap_info_size((BITMAPINFO
*)dibdata
, DIB_RGB_COLORS
);
1153 CFDataAppendBytes(ret
, (UInt8
*)&bfh
, sizeof(bfh
));
1155 /* rest of bitmap is the same as the packed dib */
1156 CFDataAppendBytes(ret
, (UInt8
*)dibdata
, len
- sizeof(bfh
));
1165 /**************************************************************************
1166 * export_hdrop_to_filenames
1168 * Export CF_HDROP to NSFilenamesPboardType data, which is a CFArray of
1169 * CFStrings (holding Unix paths) which is serialized as a property list.
1171 static CFDataRef
export_hdrop_to_filenames(HANDLE data
)
1173 CFDataRef ret
= NULL
;
1174 DROPFILES
*dropfiles
;
1175 CFMutableArrayRef filenames
= NULL
;
1177 WCHAR
*buffer
= NULL
;
1178 size_t buffer_len
= 0;
1180 TRACE("data %p\n", data
);
1182 if (!(dropfiles
= GlobalLock(data
)))
1184 WARN("failed to lock data %p\n", data
);
1188 filenames
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1191 WARN("failed to create filenames array\n");
1195 p
= (char*)dropfiles
+ dropfiles
->pFiles
;
1196 while (dropfiles
->fWide
? *(WCHAR
*)p
: *(char*)p
)
1199 CFStringRef filename
;
1201 TRACE(" %s\n", dropfiles
->fWide
? debugstr_w(p
) : debugstr_a(p
));
1203 if (dropfiles
->fWide
)
1204 unixname
= wine_get_unix_file_name(p
);
1207 int len
= MultiByteToWideChar(CP_ACP
, 0, p
, -1, NULL
, 0);
1210 if (len
> buffer_len
)
1212 HeapFree(GetProcessHeap(), 0, buffer
);
1213 buffer_len
= len
* 2;
1214 buffer
= HeapAlloc(GetProcessHeap(), 0, buffer_len
* sizeof(*buffer
));
1217 MultiByteToWideChar(CP_ACP
, 0, p
, -1, buffer
, buffer_len
);
1218 unixname
= wine_get_unix_file_name(buffer
);
1225 WARN("failed to convert DOS path to Unix: %s\n",
1226 dropfiles
->fWide
? debugstr_w(p
) : debugstr_a(p
));
1230 if (dropfiles
->fWide
)
1231 p
= (WCHAR
*)p
+ strlenW(p
) + 1;
1233 p
= (char*)p
+ strlen(p
) + 1;
1235 filename
= CFStringCreateWithFileSystemRepresentation(NULL
, unixname
);
1236 HeapFree(GetProcessHeap(), 0, unixname
);
1239 WARN("failed to create CFString from Unix path %s\n", debugstr_a(unixname
));
1243 CFArrayAppendValue(filenames
, filename
);
1244 CFRelease(filename
);
1247 ret
= CFPropertyListCreateData(NULL
, filenames
, kCFPropertyListXMLFormat_v1_0
, 0, NULL
);
1250 HeapFree(GetProcessHeap(), 0, buffer
);
1252 if (filenames
) CFRelease(filenames
);
1253 TRACE(" -> %s\n", debugstr_cf(ret
));
1258 /**************************************************************************
1259 * export_oemtext_to_utf8
1261 * Export CF_OEMTEXT to UTF-8.
1263 static CFDataRef
export_oemtext_to_utf8(HANDLE data
)
1265 return export_codepage_to_utf8(data
, CP_OEMCP
);
1269 /**************************************************************************
1270 * export_oemtext_to_utf16
1272 * Export CF_OEMTEXT to UTF-16.
1274 static CFDataRef
export_oemtext_to_utf16(HANDLE data
)
1276 return export_codepage_to_utf16(data
, CP_OEMCP
);
1280 /**************************************************************************
1281 * export_text_to_utf8
1283 * Export CF_TEXT to UTF-8.
1285 static CFDataRef
export_text_to_utf8(HANDLE data
)
1287 return export_codepage_to_utf8(data
, CP_ACP
);
1291 /**************************************************************************
1292 * export_text_to_utf16
1294 * Export CF_TEXT to UTF-16.
1296 static CFDataRef
export_text_to_utf16(HANDLE data
)
1298 return export_codepage_to_utf16(data
, CP_ACP
);
1302 /**************************************************************************
1303 * export_unicodetext_to_utf8
1305 * Export CF_UNICODETEXT to UTF-8.
1307 static CFDataRef
export_unicodetext_to_utf8(HANDLE data
)
1309 CFMutableDataRef ret
;
1313 src
= GlobalLock(data
);
1314 if (!src
) return NULL
;
1316 dst_len
= WideCharToMultiByte(CP_UTF8
, 0, src
, -1, NULL
, 0, NULL
, NULL
);
1317 if (dst_len
) dst_len
--; /* Leave off null terminator. */
1318 ret
= CFDataCreateMutable(NULL
, dst_len
);
1324 CFDataSetLength(ret
, dst_len
);
1325 dst
= (LPSTR
)CFDataGetMutableBytePtr(ret
);
1326 WideCharToMultiByte(CP_UTF8
, 0, src
, -1, dst
, dst_len
, NULL
, NULL
);
1328 /* Remove carriage returns */
1329 for (i
= 0, j
= 0; i
< dst_len
; i
++)
1331 if (dst
[i
] == '\r' &&
1332 (i
+ 1 >= dst_len
|| dst
[i
+ 1] == '\n' || dst
[i
+ 1] == '\0'))
1336 CFDataSetLength(ret
, j
);
1344 /**************************************************************************
1345 * export_unicodetext_to_utf16
1347 * Export CF_UNICODETEXT to UTF-16.
1349 static CFDataRef
export_unicodetext_to_utf16(HANDLE data
)
1351 CFMutableDataRef ret
;
1355 src
= GlobalLock(data
);
1356 if (!src
) return NULL
;
1358 src_len
= GlobalSize(data
) / sizeof(WCHAR
);
1359 if (src_len
) src_len
--; /* Leave off null terminator. */
1360 ret
= CFDataCreateMutable(NULL
, src_len
* sizeof(WCHAR
));
1366 CFDataSetLength(ret
, src_len
* sizeof(WCHAR
));
1367 dst
= (LPWSTR
)CFDataGetMutableBytePtr(ret
);
1369 /* Remove carriage returns */
1370 for (i
= 0, j
= 0; i
< src_len
; i
++)
1372 if (src
[i
] == '\r' &&
1373 (i
+ 1 >= src_len
|| src
[i
+ 1] == '\n' || src
[i
+ 1] == '\0'))
1377 CFDataSetLength(ret
, j
* sizeof(WCHAR
));
1385 /**************************************************************************
1386 * get_clipboard_info
1388 static BOOL
get_clipboard_info(LPCLIPBOARDINFO cbinfo
)
1392 SERVER_START_REQ(set_clipboard_info
)
1396 if (wine_server_call_err(req
))
1398 ERR("Failed to get clipboard owner.\n");
1402 cbinfo
->hwnd_owner
= wine_server_ptr_handle(reply
->old_owner
);
1403 cbinfo
->flags
= reply
->flags
;
1414 /**************************************************************************
1417 static BOOL
release_ownership(void)
1421 SERVER_START_REQ(set_clipboard_info
)
1423 req
->flags
= SET_CB_RELOWNER
| SET_CB_SEQNO
;
1425 if (wine_server_call_err(req
))
1426 ERR("Failed to set clipboard.\n");
1436 /**************************************************************************
1437 * macdrv_get_pasteboard_data
1439 HANDLE
macdrv_get_pasteboard_data(CFTypeRef pasteboard
, UINT desired_format
)
1444 CFStringRef type
, best_type
;
1445 WINE_CLIPFORMAT
* best_format
= NULL
;
1448 TRACE("pasteboard %p, desired_format %s\n", pasteboard
, debugstr_format(desired_format
));
1450 types
= macdrv_copy_pasteboard_types(pasteboard
);
1453 WARN("Failed to copy pasteboard types\n");
1457 count
= CFArrayGetCount(types
);
1458 TRACE("got %ld types\n", count
);
1460 for (i
= 0; (!best_format
|| best_format
->synthesized
) && i
< count
; i
++)
1462 WINE_CLIPFORMAT
* format
;
1464 type
= CFArrayGetValueAtIndex(types
, i
);
1467 while ((!best_format
|| best_format
->synthesized
) && (format
= format_for_type(format
, type
)))
1469 TRACE("for type %s got format %p/%s\n", debugstr_cf(type
), format
, debugstr_format(format
? format
->format_id
: 0));
1471 if (format
->format_id
== desired_format
)
1473 /* The best format is the matching one which is not synthesized. Failing that,
1474 the best format is the first matching synthesized format. */
1475 if (!format
->synthesized
|| !best_format
)
1478 best_format
= format
;
1486 CFDataRef pasteboard_data
= macdrv_copy_pasteboard_data(pasteboard
, best_type
);
1488 TRACE("got pasteboard data for type %s: %s\n", debugstr_cf(best_type
), debugstr_cf(pasteboard_data
));
1490 if (pasteboard_data
)
1492 data
= best_format
->import_func(pasteboard_data
);
1493 CFRelease(pasteboard_data
);
1498 TRACE(" -> %p\n", data
);
1503 /**************************************************************************
1504 * macdrv_pasteboard_has_format
1506 BOOL
macdrv_pasteboard_has_format(CFTypeRef pasteboard
, UINT desired_format
)
1513 TRACE("pasteboard %p, desired_format %s\n", pasteboard
, debugstr_format(desired_format
));
1515 types
= macdrv_copy_pasteboard_types(pasteboard
);
1518 WARN("Failed to copy pasteboard types\n");
1522 count
= CFArrayGetCount(types
);
1523 TRACE("got %d types\n", count
);
1525 for (i
= 0; !found
&& i
< count
; i
++)
1527 CFStringRef type
= CFArrayGetValueAtIndex(types
, i
);
1528 WINE_CLIPFORMAT
* format
;
1531 while (!found
&& (format
= format_for_type(format
, type
)))
1533 TRACE("for type %s got format %s\n", debugstr_cf(type
), debugstr_format(format
->format_id
));
1535 if (format
->format_id
== desired_format
)
1541 TRACE(" -> %d\n", found
);
1546 /**************************************************************************
1547 * macdrv_copy_pasteboard_formats
1549 CFArrayRef
macdrv_copy_pasteboard_formats(CFTypeRef pasteboard
)
1553 CFMutableArrayRef formats
;
1556 TRACE("pasteboard %p\n", pasteboard
);
1558 types
= macdrv_copy_pasteboard_types(pasteboard
);
1561 WARN("Failed to copy pasteboard types\n");
1565 count
= CFArrayGetCount(types
);
1566 TRACE("got %ld types\n", count
);
1574 formats
= CFArrayCreateMutable(NULL
, 0, NULL
);
1577 WARN("Failed to allocate formats array\n");
1582 for (i
= 0; i
< count
; i
++)
1584 CFStringRef type
= CFArrayGetValueAtIndex(types
, i
);
1585 WINE_CLIPFORMAT
* format
;
1588 while ((format
= format_for_type(format
, type
)))
1590 TRACE("for type %s got format %p/%s\n", debugstr_cf(type
), format
, debugstr_format(format
->format_id
));
1592 if (format
->synthesized
)
1594 /* Don't override a real value with a synthesized value. */
1595 if (!CFArrayContainsValue(formats
, CFRangeMake(0, CFArrayGetCount(formats
)), (void*)format
->format_id
))
1596 CFArrayAppendValue(formats
, (void*)format
->format_id
);
1600 /* If the type was already in the array, it must have been synthesized
1601 because this one's real. Remove the synthesized entry in favor of
1603 CFIndex index
= CFArrayGetFirstIndexOfValue(formats
, CFRangeMake(0, CFArrayGetCount(formats
)),
1604 (void*)format
->format_id
);
1605 if (index
!= kCFNotFound
)
1606 CFArrayRemoveValueAtIndex(formats
, index
);
1607 CFArrayAppendValue(formats
, (void*)format
->format_id
);
1614 TRACE(" -> %s\n", debugstr_cf(formats
));
1619 /**************************************************************************
1620 * check_clipboard_ownership
1622 static void check_clipboard_ownership(HWND
*owner
)
1624 CLIPBOARDINFO cbinfo
;
1626 if (owner
) *owner
= NULL
;
1628 /* If Wine thinks we're the clipboard owner but Mac OS X thinks we're not
1629 the pasteboard owner, update Wine. */
1630 if (get_clipboard_info(&cbinfo
) && (cbinfo
.flags
& CB_PROCESS
))
1632 if (!(cbinfo
.flags
& CB_OPEN
) && !macdrv_is_pasteboard_owner())
1634 TRACE("Lost clipboard ownership\n");
1636 if (OpenClipboard(cbinfo
.hwnd_owner
))
1638 /* Destroy private objects */
1639 SendMessageW(cbinfo
.hwnd_owner
, WM_DESTROYCLIPBOARD
, 0, 0);
1641 /* Give up ownership of the windows clipboard */
1642 release_ownership();
1647 *owner
= cbinfo
.hwnd_owner
;
1652 /**************************************************************************
1653 * Mac User Driver Clipboard Exports
1654 **************************************************************************/
1657 /**************************************************************************
1658 * AcquireClipboard (MACDRV.@)
1660 int CDECL
macdrv_AcquireClipboard(HWND hwnd
)
1662 TRACE("hwnd %p\n", hwnd
);
1663 check_clipboard_ownership(NULL
);
1668 /**************************************************************************
1669 * CountClipboardFormats (MACDRV.@)
1671 INT CDECL
macdrv_CountClipboardFormats(void)
1673 CFMutableSetRef seen_formats
;
1680 check_clipboard_ownership(NULL
);
1682 seen_formats
= CFSetCreateMutable(NULL
, 0, NULL
);
1685 WARN("Failed to allocate set to track seen formats\n");
1689 types
= macdrv_copy_pasteboard_types(NULL
);
1692 WARN("Failed to copy pasteboard types\n");
1693 CFRelease(seen_formats
);
1697 count
= CFArrayGetCount(types
);
1698 TRACE("got %ld types\n", count
);
1700 for (i
= 0; i
< count
; i
++)
1702 CFStringRef type
= CFArrayGetValueAtIndex(types
, i
);
1703 WINE_CLIPFORMAT
* format
;
1706 while ((format
= format_for_type(format
, type
)))
1708 TRACE("for type %s got format %p/%s\n", debugstr_cf(type
), format
, debugstr_format(format
->format_id
));
1710 if (!CFSetContainsValue(seen_formats
, (void*)format
->format_id
))
1713 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
);