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
);
52 typedef struct _WINE_CLIPFORMAT
57 DRVIMPORTFUNC import_func
;
58 DRVEXPORTFUNC export_func
;
60 struct _WINE_CLIPFORMAT
*natural_format
;
64 /**************************************************************************
66 **************************************************************************/
69 /**************************************************************************
70 * Forward Function Declarations
71 **************************************************************************/
73 static HANDLE
import_clipboard_data(CFDataRef data
);
74 static HANDLE
import_bmp_to_bitmap(CFDataRef data
);
75 static HANDLE
import_bmp_to_dib(CFDataRef data
);
76 static HANDLE
import_enhmetafile(CFDataRef data
);
77 static HANDLE
import_metafilepict(CFDataRef data
);
78 static HANDLE
import_nsfilenames_to_hdrop(CFDataRef data
);
79 static HANDLE
import_utf8_to_oemtext(CFDataRef data
);
80 static HANDLE
import_utf8_to_text(CFDataRef data
);
81 static HANDLE
import_utf8_to_unicodetext(CFDataRef data
);
82 static HANDLE
import_utf16_to_oemtext(CFDataRef data
);
83 static HANDLE
import_utf16_to_text(CFDataRef data
);
84 static HANDLE
import_utf16_to_unicodetext(CFDataRef data
);
86 static CFDataRef
export_clipboard_data(HANDLE data
);
87 static CFDataRef
export_bitmap_to_bmp(HANDLE data
);
88 static CFDataRef
export_dib_to_bmp(HANDLE data
);
89 static CFDataRef
export_enhmetafile(HANDLE data
);
90 static CFDataRef
export_hdrop_to_filenames(HANDLE data
);
91 static CFDataRef
export_metafilepict(HANDLE data
);
92 static CFDataRef
export_oemtext_to_utf8(HANDLE data
);
93 static CFDataRef
export_oemtext_to_utf16(HANDLE data
);
94 static CFDataRef
export_text_to_utf8(HANDLE data
);
95 static CFDataRef
export_text_to_utf16(HANDLE data
);
96 static CFDataRef
export_unicodetext_to_utf8(HANDLE data
);
97 static CFDataRef
export_unicodetext_to_utf16(HANDLE data
);
100 /**************************************************************************
102 **************************************************************************/
104 /* Clipboard formats */
105 static struct list format_list
= LIST_INIT(format_list
);
107 /* There are two naming schemes involved and we want to have a mapping between
108 them. There are Win32 clipboard format names and there are Mac pasteboard
111 The Win32 standard clipboard formats don't have names, but they are associated
112 with Mac pasteboard types through the following tables, which are used to
113 initialize the format_list. Where possible, the standard clipboard formats
114 are mapped to predefined pasteboard type UTIs. Otherwise, we create Wine-
115 specific types of the form "org.winehq.builtin.<format>", where <format> is
116 the name of the symbolic constant for the format minus "CF_" and lowercased.
117 E.g. CF_BITMAP -> org.winehq.builtin.bitmap.
119 Win32 clipboard formats which originate in a Windows program may be registered
120 with an arbitrary name. We construct a Mac pasteboard type from these by
121 prepending "org.winehq.registered." to the registered name.
123 Likewise, Mac pasteboard types which originate in other apps may have
124 arbitrary type strings. We ignore these.
127 Win32 clipboard format names:
128 <none> standard clipboard format; maps via
129 format_list to either a predefined Mac UTI
130 or org.winehq.builtin.<format>.
131 <other> name registered within Win32 land; maps to
132 org.winehq.registered.<other>
133 Mac pasteboard type names:
134 org.winehq.builtin.<format ID> representation of Win32 standard clipboard
135 format for which there was no corresponding
136 predefined Mac UTI; maps via format_list
137 org.winehq.registered.<format name> representation of Win32 registered
138 clipboard format name; maps to <format name>
139 <other> Mac pasteboard type originating with system
140 or other apps; either maps via format_list
141 to a standard clipboard format or ignored
148 DRVIMPORTFUNC import
;
149 DRVEXPORTFUNC export
;
151 } builtin_format_ids
[] =
153 { CF_DIF
, CFSTR("org.winehq.builtin.dif"), import_clipboard_data
, export_clipboard_data
, FALSE
},
154 { CF_ENHMETAFILE
, CFSTR("org.winehq.builtin.enhmetafile"), import_enhmetafile
, export_enhmetafile
, FALSE
},
155 { CF_LOCALE
, CFSTR("org.winehq.builtin.locale"), import_clipboard_data
, export_clipboard_data
, FALSE
},
156 { CF_METAFILEPICT
, CFSTR("org.winehq.builtin.metafilepict"), import_metafilepict
, export_metafilepict
, FALSE
},
157 { CF_PALETTE
, CFSTR("org.winehq.builtin.palette"), import_clipboard_data
, export_clipboard_data
, FALSE
},
158 { CF_PENDATA
, CFSTR("org.winehq.builtin.pendata"), import_clipboard_data
, export_clipboard_data
, FALSE
},
159 { CF_RIFF
, CFSTR("org.winehq.builtin.riff"), import_clipboard_data
, export_clipboard_data
, FALSE
},
160 { CF_SYLK
, CFSTR("org.winehq.builtin.sylk"), import_clipboard_data
, export_clipboard_data
, FALSE
},
161 { CF_TIFF
, CFSTR("public.tiff"), import_clipboard_data
, export_clipboard_data
, FALSE
},
162 { CF_WAVE
, CFSTR("com.microsoft.waveform-audio"), import_clipboard_data
, export_clipboard_data
, FALSE
},
164 { CF_BITMAP
, CFSTR("org.winehq.builtin.bitmap"), import_bmp_to_bitmap
, export_bitmap_to_bmp
, FALSE
},
165 { CF_BITMAP
, CFSTR("com.microsoft.bmp"), import_bmp_to_bitmap
, export_bitmap_to_bmp
, TRUE
},
167 { CF_DIB
, CFSTR("org.winehq.builtin.dib"), import_clipboard_data
, export_clipboard_data
, FALSE
},
168 { CF_DIB
, CFSTR("com.microsoft.bmp"), import_bmp_to_dib
, export_dib_to_bmp
, TRUE
},
170 { CF_DIBV5
, CFSTR("org.winehq.builtin.dibv5"), import_clipboard_data
, export_clipboard_data
, FALSE
},
171 { CF_DIBV5
, CFSTR("com.microsoft.bmp"), import_bmp_to_dib
, export_dib_to_bmp
, TRUE
},
173 { CF_HDROP
, CFSTR("org.winehq.builtin.hdrop"), import_clipboard_data
, export_clipboard_data
, FALSE
},
174 { CF_HDROP
, CFSTR("NSFilenamesPboardType"), import_nsfilenames_to_hdrop
, export_hdrop_to_filenames
, TRUE
},
176 { CF_OEMTEXT
, CFSTR("org.winehq.builtin.oemtext"), import_clipboard_data
, export_clipboard_data
, FALSE
},
177 { CF_OEMTEXT
, CFSTR("public.utf16-plain-text"), import_utf16_to_oemtext
, export_oemtext_to_utf16
, TRUE
},
178 { CF_OEMTEXT
, CFSTR("public.utf8-plain-text"), import_utf8_to_oemtext
, export_oemtext_to_utf8
, TRUE
},
180 { CF_TEXT
, CFSTR("org.winehq.builtin.text"), import_clipboard_data
, export_clipboard_data
, FALSE
},
181 { CF_TEXT
, CFSTR("public.utf16-plain-text"), import_utf16_to_text
, export_text_to_utf16
, TRUE
},
182 { CF_TEXT
, CFSTR("public.utf8-plain-text"), import_utf8_to_text
, export_text_to_utf8
, TRUE
},
184 { CF_UNICODETEXT
, CFSTR("org.winehq.builtin.unicodetext"), import_clipboard_data
, export_clipboard_data
, FALSE
},
185 { CF_UNICODETEXT
, CFSTR("public.utf16-plain-text"), import_utf16_to_unicodetext
, export_unicodetext_to_utf16
,TRUE
},
186 { CF_UNICODETEXT
, CFSTR("public.utf8-plain-text"), import_utf8_to_unicodetext
, export_unicodetext_to_utf8
, TRUE
},
189 static const WCHAR wszRichTextFormat
[] = {'R','i','c','h',' ','T','e','x','t',' ','F','o','r','m','a','t',0};
190 static const WCHAR wszGIF
[] = {'G','I','F',0};
191 static const WCHAR wszJFIF
[] = {'J','F','I','F',0};
192 static const WCHAR wszPNG
[] = {'P','N','G',0};
193 static const WCHAR wszHTMLFormat
[] = {'H','T','M','L',' ','F','o','r','m','a','t',0};
198 DRVIMPORTFUNC import
;
199 DRVEXPORTFUNC export
;
200 } builtin_format_names
[] =
202 { wszRichTextFormat
, CFSTR("public.rtf"), import_clipboard_data
, export_clipboard_data
},
203 { wszGIF
, CFSTR("com.compuserve.gif"), import_clipboard_data
, export_clipboard_data
},
204 { wszJFIF
, CFSTR("public.jpeg"), import_clipboard_data
, export_clipboard_data
},
205 { wszPNG
, CFSTR("public.png"), import_clipboard_data
, export_clipboard_data
},
206 { wszHTMLFormat
, CFSTR("public.html"), import_clipboard_data
, export_clipboard_data
},
207 { CFSTR_SHELLURLW
, CFSTR("public.url"), import_utf8_to_text
, export_text_to_utf8
},
210 /* The prefix prepended to a Win32 clipboard format name to make a Mac pasteboard type. */
211 static const CFStringRef registered_name_type_prefix
= CFSTR("org.winehq.registered.");
214 /**************************************************************************
215 * Internal Clipboard implementation methods
216 **************************************************************************/
219 * format_list functions
222 /**************************************************************************
225 const char *debugstr_format(UINT id
)
229 if (GetClipboardFormatNameW(id
, buffer
, 256))
230 return wine_dbg_sprintf("0x%04x %s", id
, debugstr_w(buffer
));
234 #define BUILTIN(id) case id: return #id;
237 BUILTIN(CF_METAFILEPICT
)
247 BUILTIN(CF_UNICODETEXT
)
248 BUILTIN(CF_ENHMETAFILE
)
252 BUILTIN(CF_OWNERDISPLAY
)
254 BUILTIN(CF_DSPBITMAP
)
255 BUILTIN(CF_DSPMETAFILEPICT
)
256 BUILTIN(CF_DSPENHMETAFILE
)
258 default: return wine_dbg_sprintf("0x%04x", id
);
263 /**************************************************************************
264 * insert_clipboard_format
266 static WINE_CLIPFORMAT
*insert_clipboard_format(UINT id
, CFStringRef type
)
268 WINE_CLIPFORMAT
*format
;
270 format
= HeapAlloc(GetProcessHeap(), 0, sizeof(*format
));
274 WARN("No more memory for a new format!\n");
277 format
->format_id
= id
;
278 format
->import_func
= import_clipboard_data
;
279 format
->export_func
= export_clipboard_data
;
280 format
->synthesized
= FALSE
;
281 format
->natural_format
= NULL
;
284 format
->type
= CFStringCreateCopy(NULL
, type
);
289 if (!GetClipboardFormatNameW(format
->format_id
, buffer
, sizeof(buffer
) / sizeof(buffer
[0])))
291 WARN("failed to get name for format %s; error 0x%08x\n", debugstr_format(format
->format_id
), GetLastError());
292 HeapFree(GetProcessHeap(), 0, format
);
296 format
->type
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@%S"),
297 registered_name_type_prefix
, buffer
);
300 list_add_tail(&format_list
, &format
->entry
);
302 TRACE("Registering format %s type %s\n", debugstr_format(format
->format_id
),
303 debugstr_cf(format
->type
));
309 /**************************************************************************
312 * Register a custom Mac clipboard format.
314 static WINE_CLIPFORMAT
* register_format(UINT id
, CFStringRef type
)
316 WINE_CLIPFORMAT
*format
;
318 /* walk format chain to see if it's already registered */
319 LIST_FOR_EACH_ENTRY(format
, &format_list
, WINE_CLIPFORMAT
, entry
)
320 if (format
->format_id
== id
) return format
;
322 return insert_clipboard_format(id
, type
);
326 /**************************************************************************
329 static WINE_CLIPFORMAT
* format_for_type(WINE_CLIPFORMAT
*current
, CFStringRef type
)
331 struct list
*ptr
= current
? ¤t
->entry
: &format_list
;
332 WINE_CLIPFORMAT
*format
= NULL
;
334 TRACE("current %p/%s type %s\n", current
, debugstr_format(current
? current
->format_id
: 0), debugstr_cf(type
));
336 while ((ptr
= list_next(&format_list
, ptr
)))
338 format
= LIST_ENTRY(ptr
, WINE_CLIPFORMAT
, entry
);
339 if (CFEqual(format
->type
, type
))
346 if (CFStringHasPrefix(type
, CFSTR("org.winehq.builtin.")))
348 ERR("Shouldn't happen. Built-in type %s should have matched something in format list.\n",
351 else if (CFStringHasPrefix(type
, registered_name_type_prefix
))
354 int len
= CFStringGetLength(type
) - CFStringGetLength(registered_name_type_prefix
);
356 name
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
));
357 CFStringGetCharacters(type
, CFRangeMake(CFStringGetLength(registered_name_type_prefix
), len
),
361 format
= register_format(RegisterClipboardFormatW(name
), type
);
363 ERR("Failed to register format for type %s name %s\n", debugstr_cf(type
), debugstr_w(name
));
365 HeapFree(GetProcessHeap(), 0, name
);
370 TRACE(" -> %p/%s\n", format
, debugstr_format(format
? format
->format_id
: 0));
375 /**************************************************************************
376 * natural_format_for_format
378 * Find the "natural" format for this format_id (the one which isn't
379 * synthesized from another type).
381 static WINE_CLIPFORMAT
* natural_format_for_format(UINT format_id
)
383 WINE_CLIPFORMAT
*format
;
385 LIST_FOR_EACH_ENTRY(format
, &format_list
, WINE_CLIPFORMAT
, entry
)
386 if (format
->format_id
== format_id
&& !format
->synthesized
) break;
388 if (&format
->entry
== &format_list
)
391 TRACE("%s -> %p/%s\n", debugstr_format(format_id
), format
, debugstr_cf(format
? format
->type
: NULL
));
396 /**************************************************************************
399 * Convert string data between code pages or to/from wide characters. The
400 * special value of (UINT)-1 for a code page indicates to use wide
403 static HANDLE
convert_text(const void *src
, int src_len
, UINT src_cp
, UINT dest_cp
)
411 if (src_cp
== (UINT
)-1)
414 wstr_len
= src_len
/ sizeof(WCHAR
);
420 wstr_len
= MultiByteToWideChar(src_cp
, 0, src
, src_len
, NULL
, 0);
421 if (!src_len
|| ((const char*)src
)[src_len
- 1]) wstr_len
+= 1;
422 temp
= HeapAlloc(GetProcessHeap(), 0, wstr_len
* sizeof(WCHAR
));
423 MultiByteToWideChar(src_cp
, 0, src
, src_len
, temp
, wstr_len
);
424 temp
[wstr_len
- 1] = 0;
428 if (dest_cp
== (UINT
)-1)
430 handle
= GlobalAlloc(GMEM_FIXED
, wstr_len
* sizeof(WCHAR
));
431 if (handle
&& (p
= GlobalLock(handle
)))
433 memcpy(p
, wstr
, wstr_len
* sizeof(WCHAR
));
434 GlobalUnlock(handle
);
442 len
= WideCharToMultiByte(dest_cp
, 0, wstr
, wstr_len
, NULL
, 0, NULL
, NULL
);
443 if (!wstr_len
|| wstr
[wstr_len
- 1]) len
+= 1;
444 handle
= GlobalAlloc(GMEM_FIXED
, len
);
446 if (handle
&& (p
= GlobalLock(handle
)))
448 WideCharToMultiByte(dest_cp
, 0, wstr
, wstr_len
, p
, len
, NULL
, NULL
);
450 GlobalUnlock(handle
);
459 /**************************************************************************
460 * convert_unicodetext_to_codepage
462 static HANDLE
convert_unicodetext_to_codepage(HANDLE unicode_handle
, UINT cp
)
464 LPWSTR unicode_string
= GlobalLock(unicode_handle
);
469 ret
= convert_text(unicode_string
, GlobalSize(unicode_handle
), -1, cp
);
470 GlobalUnlock(unicode_handle
);
477 /***********************************************************************
480 * Return the size of the bitmap info structure including color table.
482 static int bitmap_info_size(const BITMAPINFO
*info
, WORD coloruse
)
484 unsigned int colors
, size
, masks
= 0;
486 if (info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
488 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)info
;
489 colors
= (core
->bcBitCount
<= 8) ? 1 << core
->bcBitCount
: 0;
490 return sizeof(BITMAPCOREHEADER
) + colors
*
491 ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBTRIPLE
) : sizeof(WORD
));
493 else /* assume BITMAPINFOHEADER */
495 colors
= info
->bmiHeader
.biClrUsed
;
496 if (!colors
&& (info
->bmiHeader
.biBitCount
<= 8))
497 colors
= 1 << info
->bmiHeader
.biBitCount
;
498 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
) masks
= 3;
499 size
= max(info
->bmiHeader
.biSize
, sizeof(BITMAPINFOHEADER
) + masks
* sizeof(DWORD
));
500 return size
+ colors
* ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBQUAD
) : sizeof(WORD
));
505 /***********************************************************************
506 * create_dib_from_bitmap
508 * Allocates a packed DIB and copies the bitmap data into it.
510 static HGLOBAL
create_dib_from_bitmap(HBITMAP hBmp
)
516 LPBITMAPINFOHEADER pbmiHeader
;
517 unsigned int cDataSize
, cPackedSize
, OffsetBits
;
520 if (!GetObjectW(hBmp
, sizeof(bmp
), &bmp
)) return 0;
523 * A packed DIB contains a BITMAPINFO structure followed immediately by
524 * an optional color palette and the pixel data.
527 /* Calculate the size of the packed DIB */
528 cDataSize
= abs(bmp
.bmHeight
) * (((bmp
.bmWidth
* bmp
.bmBitsPixel
+ 31) / 8) & ~3);
529 cPackedSize
= sizeof(BITMAPINFOHEADER
)
530 + ((bmp
.bmBitsPixel
<= 8) ? (sizeof(RGBQUAD
) * (1 << bmp
.bmBitsPixel
)) : 0)
532 /* Get the offset to the bits */
533 OffsetBits
= cPackedSize
- cDataSize
;
535 /* Allocate the packed DIB */
536 TRACE("\tAllocating packed DIB of size %d\n", cPackedSize
);
537 hPackedDIB
= GlobalAlloc(GMEM_FIXED
, cPackedSize
);
540 WARN("Could not allocate packed DIB!\n");
544 /* A packed DIB starts with a BITMAPINFOHEADER */
545 pPackedDIB
= GlobalLock(hPackedDIB
);
546 pbmiHeader
= (LPBITMAPINFOHEADER
)pPackedDIB
;
548 /* Init the BITMAPINFOHEADER */
549 pbmiHeader
->biSize
= sizeof(BITMAPINFOHEADER
);
550 pbmiHeader
->biWidth
= bmp
.bmWidth
;
551 pbmiHeader
->biHeight
= bmp
.bmHeight
;
552 pbmiHeader
->biPlanes
= 1;
553 pbmiHeader
->biBitCount
= bmp
.bmBitsPixel
;
554 pbmiHeader
->biCompression
= BI_RGB
;
555 pbmiHeader
->biSizeImage
= 0;
556 pbmiHeader
->biXPelsPerMeter
= pbmiHeader
->biYPelsPerMeter
= 0;
557 pbmiHeader
->biClrUsed
= 0;
558 pbmiHeader
->biClrImportant
= 0;
560 /* Retrieve the DIB bits from the bitmap and fill in the
561 * DIB color table if present */
563 nLinesCopied
= GetDIBits(hdc
, /* Handle to device context */
564 hBmp
, /* Handle to bitmap */
565 0, /* First scan line to set in dest bitmap */
566 bmp
.bmHeight
, /* Number of scan lines to copy */
567 pPackedDIB
+ OffsetBits
, /* [out] Address of array for bitmap bits */
568 (LPBITMAPINFO
) pbmiHeader
, /* [out] Address of BITMAPINFO structure */
569 0); /* RGB or palette index */
570 GlobalUnlock(hPackedDIB
);
573 /* Cleanup if GetDIBits failed */
574 if (nLinesCopied
!= bmp
.bmHeight
)
576 TRACE("\tGetDIBits returned %d. Actual lines=%d\n", nLinesCopied
, bmp
.bmHeight
);
577 GlobalFree(hPackedDIB
);
584 /**************************************************************************
585 * create_bitmap_from_dib
587 * Given a packed DIB, creates a bitmap object from it.
589 static HANDLE
create_bitmap_from_dib(HANDLE dib
)
594 if (dib
&& (bmi
= GlobalLock(dib
)))
601 offset
= bitmap_info_size(bmi
, DIB_RGB_COLORS
);
603 ret
= CreateDIBitmap(hdc
, &bmi
->bmiHeader
, CBM_INIT
, (LPBYTE
)bmi
+ offset
,
604 bmi
, DIB_RGB_COLORS
);
607 ReleaseDC(NULL
, hdc
);
614 /**************************************************************************
615 * import_clipboard_data
617 * Generic import clipboard data routine.
619 static HANDLE
import_clipboard_data(CFDataRef data
)
621 HANDLE data_handle
= NULL
;
623 size_t len
= CFDataGetLength(data
);
628 /* Turn on the DDESHARE flag to enable shared 32 bit memory */
629 data_handle
= GlobalAlloc(GMEM_FIXED
, len
);
633 if ((p
= GlobalLock(data_handle
)))
635 memcpy(p
, CFDataGetBytePtr(data
), len
);
636 GlobalUnlock(data_handle
);
640 GlobalFree(data_handle
);
649 /**************************************************************************
650 * import_bmp_to_bitmap
652 * Import BMP data, converting to CF_BITMAP format.
654 static HANDLE
import_bmp_to_bitmap(CFDataRef data
)
657 HANDLE dib
= import_bmp_to_dib(data
);
659 ret
= create_bitmap_from_dib(dib
);
666 /**************************************************************************
669 * Import BMP data, converting to CF_DIB or CF_DIBV5 format. This just
670 * entails stripping the BMP file format header.
672 static HANDLE
import_bmp_to_dib(CFDataRef data
)
675 BITMAPFILEHEADER
*bfh
= (BITMAPFILEHEADER
*)CFDataGetBytePtr(data
);
676 CFIndex len
= CFDataGetLength(data
);
678 if (len
>= sizeof(*bfh
) + sizeof(BITMAPCOREHEADER
) &&
679 bfh
->bfType
== 0x4d42 /* "BM" */)
681 BITMAPINFO
*bmi
= (BITMAPINFO
*)(bfh
+ 1);
685 ret
= GlobalAlloc(GMEM_FIXED
, len
);
686 if (!ret
|| !(p
= GlobalLock(ret
)))
700 /**************************************************************************
703 * Import enhanced metafile data, converting it to CF_ENHMETAFILE.
705 static HANDLE
import_enhmetafile(CFDataRef data
)
708 CFIndex len
= CFDataGetLength(data
);
710 TRACE("data %s\n", debugstr_cf(data
));
713 ret
= SetEnhMetaFileBits(len
, (const BYTE
*)CFDataGetBytePtr(data
));
719 /**************************************************************************
720 * import_metafilepict
722 * Import metafile picture data, converting it to CF_METAFILEPICT.
724 static HANDLE
import_metafilepict(CFDataRef data
)
727 CFIndex len
= CFDataGetLength(data
);
730 TRACE("data %s\n", debugstr_cf(data
));
732 if (len
>= sizeof(*mfp
) && (ret
= GlobalAlloc(GMEM_FIXED
, sizeof(*mfp
))))
734 const BYTE
*bytes
= (const BYTE
*)CFDataGetBytePtr(data
);
736 mfp
= GlobalLock(ret
);
737 memcpy(mfp
, bytes
, sizeof(*mfp
));
738 mfp
->hMF
= SetMetaFileBitsEx(len
- sizeof(*mfp
), bytes
+ sizeof(*mfp
));
746 /**************************************************************************
747 * import_nsfilenames_to_hdrop
749 * Import NSFilenamesPboardType data, converting the property-list-
750 * serialized array of path strings to CF_HDROP.
752 static HANDLE
import_nsfilenames_to_hdrop(CFDataRef data
)
759 WCHAR
**paths
= NULL
;
760 DROPFILES
* dropfiles
;
763 TRACE("data %s\n", debugstr_cf(data
));
765 names
= (CFArrayRef
)CFPropertyListCreateWithData(NULL
, data
, kCFPropertyListImmutable
,
767 if (!names
|| CFGetTypeID(names
) != CFArrayGetTypeID())
769 WARN("failed to interpret data as a CFArray\n");
773 count
= CFArrayGetCount(names
);
776 for (i
= 0; i
< count
; i
++)
779 CFStringRef name
= (CFStringRef
)CFArrayGetValueAtIndex(names
, i
);
780 TRACE(" %s\n", debugstr_cf(name
));
781 if (CFGetTypeID(name
) != CFStringGetTypeID())
783 WARN("non-string in array\n");
787 this_len
= CFStringGetMaximumSizeOfFileSystemRepresentation(name
);
792 buffer
= HeapAlloc(GetProcessHeap(), 0, len
);
795 WARN("failed to allocate buffer for file-system representations\n");
799 paths
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, count
* sizeof(paths
[0]));
802 WARN("failed to allocate array of DOS paths\n");
806 for (i
= 0; i
< count
; i
++)
808 CFStringRef name
= (CFStringRef
)CFArrayGetValueAtIndex(names
, i
);
809 if (!CFStringGetFileSystemRepresentation(name
, buffer
, len
))
811 WARN("failed to get file-system representation for %s\n", debugstr_cf(name
));
814 paths
[i
] = wine_get_dos_file_name(buffer
);
817 WARN("failed to get DOS path for %s\n", debugstr_a(buffer
));
822 len
= 1; /* for the terminating null */
823 for (i
= 0; i
< count
; i
++)
824 len
+= strlenW(paths
[i
]) + 1;
826 hdrop
= GlobalAlloc(GMEM_FIXED
, sizeof(*dropfiles
) + len
* sizeof(WCHAR
));
827 if (!hdrop
|| !(dropfiles
= GlobalLock(hdrop
)))
829 WARN("failed to allocate HDROP\n");
835 dropfiles
->pFiles
= sizeof(*dropfiles
);
838 dropfiles
->fNC
= FALSE
;
839 dropfiles
->fWide
= TRUE
;
841 p
= (WCHAR
*)(dropfiles
+ 1);
842 for (i
= 0; i
< count
; i
++)
844 strcpyW(p
, paths
[i
]);
854 for (i
= 0; i
< count
; i
++)
855 HeapFree(GetProcessHeap(), 0, paths
[i
]);
856 HeapFree(GetProcessHeap(), 0, paths
);
858 HeapFree(GetProcessHeap(), 0, buffer
);
859 if (names
) CFRelease(names
);
864 /**************************************************************************
865 * import_utf8_to_oemtext
867 * Import a UTF-8 string, converting the string to CF_OEMTEXT.
869 static HANDLE
import_utf8_to_oemtext(CFDataRef data
)
871 HANDLE unicode_handle
= import_utf8_to_unicodetext(data
);
872 HANDLE ret
= convert_unicodetext_to_codepage(unicode_handle
, CP_OEMCP
);
874 GlobalFree(unicode_handle
);
879 /**************************************************************************
880 * import_utf8_to_text
882 * Import a UTF-8 string, converting the string to CF_TEXT.
884 static HANDLE
import_utf8_to_text(CFDataRef data
)
886 HANDLE unicode_handle
= import_utf8_to_unicodetext(data
);
887 HANDLE ret
= convert_unicodetext_to_codepage(unicode_handle
, CP_ACP
);
889 GlobalFree(unicode_handle
);
894 /**************************************************************************
895 * import_utf8_to_unicodetext
897 * Import a UTF-8 string, converting the string to CF_UNICODETEXT.
899 static HANDLE
import_utf8_to_unicodetext(CFDataRef data
)
902 unsigned long src_len
;
903 unsigned long new_lines
= 0;
906 HANDLE unicode_handle
= NULL
;
908 src
= CFDataGetBytePtr(data
);
909 src_len
= CFDataGetLength(data
);
910 for (i
= 0; i
< src_len
; i
++)
916 if ((dst
= HeapAlloc(GetProcessHeap(), 0, src_len
+ new_lines
+ 1)))
920 for (i
= 0, j
= 0; i
< src_len
; i
++)
929 count
= MultiByteToWideChar(CP_UTF8
, 0, dst
, -1, NULL
, 0);
930 unicode_handle
= GlobalAlloc(GMEM_FIXED
, count
* sizeof(WCHAR
));
934 WCHAR
*textW
= GlobalLock(unicode_handle
);
935 MultiByteToWideChar(CP_UTF8
, 0, dst
, -1, textW
, count
);
936 GlobalUnlock(unicode_handle
);
939 HeapFree(GetProcessHeap(), 0, dst
);
942 return unicode_handle
;
946 /**************************************************************************
947 * import_utf16_to_oemtext
949 * Import a UTF-16 string, converting the string to CF_OEMTEXT.
951 static HANDLE
import_utf16_to_oemtext(CFDataRef data
)
953 HANDLE unicode_handle
= import_utf16_to_unicodetext(data
);
954 HANDLE ret
= convert_unicodetext_to_codepage(unicode_handle
, CP_OEMCP
);
956 GlobalFree(unicode_handle
);
961 /**************************************************************************
962 * import_utf16_to_text
964 * Import a UTF-16 string, converting the string to CF_TEXT.
966 static HANDLE
import_utf16_to_text(CFDataRef data
)
968 HANDLE unicode_handle
= import_utf16_to_unicodetext(data
);
969 HANDLE ret
= convert_unicodetext_to_codepage(unicode_handle
, CP_ACP
);
971 GlobalFree(unicode_handle
);
976 /**************************************************************************
977 * import_utf16_to_unicodetext
979 * Import a UTF-8 string, converting the string to CF_UNICODETEXT.
981 static HANDLE
import_utf16_to_unicodetext(CFDataRef data
)
984 unsigned long src_len
;
985 unsigned long new_lines
= 0;
988 HANDLE unicode_handle
;
990 src
= (const WCHAR
*)CFDataGetBytePtr(data
);
991 src_len
= CFDataGetLength(data
) / sizeof(WCHAR
);
992 for (i
= 0; i
< src_len
; i
++)
996 else if (src
[i
] == '\r' && (i
+ 1 >= src_len
|| src
[i
+ 1] != '\n'))
1000 if ((unicode_handle
= GlobalAlloc(GMEM_FIXED
, (src_len
+ new_lines
+ 1) * sizeof(WCHAR
))))
1002 dst
= GlobalLock(unicode_handle
);
1004 for (i
= 0, j
= 0; i
< src_len
; i
++)
1011 if (src
[i
] == '\r' && (i
+ 1 >= src_len
|| src
[i
+ 1] != '\n'))
1016 GlobalUnlock(unicode_handle
);
1019 return unicode_handle
;
1023 /**************************************************************************
1024 * export_clipboard_data
1026 * Generic export clipboard data routine.
1028 static CFDataRef
export_clipboard_data(HANDLE data
)
1034 len
= GlobalSize(data
);
1035 src
= GlobalLock(data
);
1036 if (!src
) return NULL
;
1038 ret
= CFDataCreate(NULL
, src
, len
);
1045 /**************************************************************************
1046 * export_bitmap_to_bmp
1048 * Export CF_BITMAP to BMP file format.
1050 static CFDataRef
export_bitmap_to_bmp(HANDLE data
)
1052 CFDataRef ret
= NULL
;
1055 dib
= create_dib_from_bitmap(data
);
1058 ret
= export_dib_to_bmp(dib
);
1066 /**************************************************************************
1067 * export_codepage_to_utf8
1069 * Export string data in a specified codepage to UTF-8.
1071 static CFDataRef
export_codepage_to_utf8(HANDLE data
, UINT cp
)
1073 CFDataRef ret
= NULL
;
1076 if ((str
= GlobalLock(data
)))
1078 HANDLE unicode
= convert_text(str
, GlobalSize(data
), cp
, -1);
1080 ret
= export_unicodetext_to_utf8(unicode
);
1082 GlobalFree(unicode
);
1090 /**************************************************************************
1091 * export_codepage_to_utf16
1093 * Export string data in a specified codepage to UTF-16.
1095 static CFDataRef
export_codepage_to_utf16(HANDLE data
, UINT cp
)
1097 CFDataRef ret
= NULL
;
1100 if ((str
= GlobalLock(data
)))
1102 HANDLE unicode
= convert_text(str
, GlobalSize(data
), cp
, -1);
1104 ret
= export_unicodetext_to_utf16(unicode
);
1106 GlobalFree(unicode
);
1114 /**************************************************************************
1117 * Export CF_DIB or CF_DIBV5 to BMP file format. This just entails
1118 * prepending a BMP file format header to the data.
1120 static CFDataRef
export_dib_to_bmp(HANDLE data
)
1122 CFMutableDataRef ret
= NULL
;
1125 BITMAPFILEHEADER bfh
;
1127 dibdata
= GlobalLock(data
);
1131 len
= sizeof(bfh
) + GlobalSize(data
);
1132 ret
= CFDataCreateMutable(NULL
, len
);
1135 bfh
.bfType
= 0x4d42; /* "BM" */
1137 bfh
.bfReserved1
= 0;
1138 bfh
.bfReserved2
= 0;
1139 bfh
.bfOffBits
= sizeof(bfh
) + bitmap_info_size((BITMAPINFO
*)dibdata
, DIB_RGB_COLORS
);
1140 CFDataAppendBytes(ret
, (UInt8
*)&bfh
, sizeof(bfh
));
1142 /* rest of bitmap is the same as the packed dib */
1143 CFDataAppendBytes(ret
, (UInt8
*)dibdata
, len
- sizeof(bfh
));
1152 /**************************************************************************
1153 * export_enhmetafile
1155 * Export an enhanced metafile to data.
1157 static CFDataRef
export_enhmetafile(HANDLE data
)
1159 CFMutableDataRef ret
= NULL
;
1160 unsigned int size
= GetEnhMetaFileBits(data
, 0, NULL
);
1162 TRACE("data %p\n", data
);
1164 ret
= CFDataCreateMutable(NULL
, size
);
1167 CFDataSetLength(ret
, size
);
1168 GetEnhMetaFileBits(data
, size
, (BYTE
*)CFDataGetMutableBytePtr(ret
));
1171 TRACE(" -> %s\n", debugstr_cf(ret
));
1176 /**************************************************************************
1177 * export_hdrop_to_filenames
1179 * Export CF_HDROP to NSFilenamesPboardType data, which is a CFArray of
1180 * CFStrings (holding Unix paths) which is serialized as a property list.
1182 static CFDataRef
export_hdrop_to_filenames(HANDLE data
)
1184 CFDataRef ret
= NULL
;
1185 DROPFILES
*dropfiles
;
1186 CFMutableArrayRef filenames
= NULL
;
1188 WCHAR
*buffer
= NULL
;
1189 size_t buffer_len
= 0;
1191 TRACE("data %p\n", data
);
1193 if (!(dropfiles
= GlobalLock(data
)))
1195 WARN("failed to lock data %p\n", data
);
1199 filenames
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1202 WARN("failed to create filenames array\n");
1206 p
= (char*)dropfiles
+ dropfiles
->pFiles
;
1207 while (dropfiles
->fWide
? *(WCHAR
*)p
: *(char*)p
)
1210 CFStringRef filename
;
1212 TRACE(" %s\n", dropfiles
->fWide
? debugstr_w(p
) : debugstr_a(p
));
1214 if (dropfiles
->fWide
)
1215 unixname
= wine_get_unix_file_name(p
);
1218 int len
= MultiByteToWideChar(CP_ACP
, 0, p
, -1, NULL
, 0);
1221 if (len
> buffer_len
)
1223 HeapFree(GetProcessHeap(), 0, buffer
);
1224 buffer_len
= len
* 2;
1225 buffer
= HeapAlloc(GetProcessHeap(), 0, buffer_len
* sizeof(*buffer
));
1228 MultiByteToWideChar(CP_ACP
, 0, p
, -1, buffer
, buffer_len
);
1229 unixname
= wine_get_unix_file_name(buffer
);
1236 WARN("failed to convert DOS path to Unix: %s\n",
1237 dropfiles
->fWide
? debugstr_w(p
) : debugstr_a(p
));
1241 if (dropfiles
->fWide
)
1242 p
= (WCHAR
*)p
+ strlenW(p
) + 1;
1244 p
= (char*)p
+ strlen(p
) + 1;
1246 filename
= CFStringCreateWithFileSystemRepresentation(NULL
, unixname
);
1247 HeapFree(GetProcessHeap(), 0, unixname
);
1250 WARN("failed to create CFString from Unix path %s\n", debugstr_a(unixname
));
1254 CFArrayAppendValue(filenames
, filename
);
1255 CFRelease(filename
);
1258 ret
= CFPropertyListCreateData(NULL
, filenames
, kCFPropertyListXMLFormat_v1_0
, 0, NULL
);
1261 HeapFree(GetProcessHeap(), 0, buffer
);
1263 if (filenames
) CFRelease(filenames
);
1264 TRACE(" -> %s\n", debugstr_cf(ret
));
1269 /**************************************************************************
1270 * export_metafilepict
1272 * Export a metafile to data.
1274 static CFDataRef
export_metafilepict(HANDLE data
)
1276 CFMutableDataRef ret
= NULL
;
1277 METAFILEPICT
*mfp
= GlobalLock(data
);
1278 unsigned int size
= GetMetaFileBitsEx(mfp
->hMF
, 0, NULL
);
1280 TRACE("data %p\n", data
);
1282 ret
= CFDataCreateMutable(NULL
, sizeof(*mfp
) + size
);
1285 CFDataAppendBytes(ret
, (UInt8
*)mfp
, sizeof(*mfp
));
1286 CFDataIncreaseLength(ret
, size
);
1287 GetMetaFileBitsEx(mfp
->hMF
, size
, (BYTE
*)CFDataGetMutableBytePtr(ret
) + sizeof(*mfp
));
1291 TRACE(" -> %s\n", debugstr_cf(ret
));
1296 /**************************************************************************
1297 * export_oemtext_to_utf8
1299 * Export CF_OEMTEXT to UTF-8.
1301 static CFDataRef
export_oemtext_to_utf8(HANDLE data
)
1303 return export_codepage_to_utf8(data
, CP_OEMCP
);
1307 /**************************************************************************
1308 * export_oemtext_to_utf16
1310 * Export CF_OEMTEXT to UTF-16.
1312 static CFDataRef
export_oemtext_to_utf16(HANDLE data
)
1314 return export_codepage_to_utf16(data
, CP_OEMCP
);
1318 /**************************************************************************
1319 * export_text_to_utf8
1321 * Export CF_TEXT to UTF-8.
1323 static CFDataRef
export_text_to_utf8(HANDLE data
)
1325 return export_codepage_to_utf8(data
, CP_ACP
);
1329 /**************************************************************************
1330 * export_text_to_utf16
1332 * Export CF_TEXT to UTF-16.
1334 static CFDataRef
export_text_to_utf16(HANDLE data
)
1336 return export_codepage_to_utf16(data
, CP_ACP
);
1340 /**************************************************************************
1341 * export_unicodetext_to_utf8
1343 * Export CF_UNICODETEXT to UTF-8.
1345 static CFDataRef
export_unicodetext_to_utf8(HANDLE data
)
1347 CFMutableDataRef ret
;
1351 src
= GlobalLock(data
);
1352 if (!src
) return NULL
;
1354 dst_len
= WideCharToMultiByte(CP_UTF8
, 0, src
, -1, NULL
, 0, NULL
, NULL
);
1355 if (dst_len
) dst_len
--; /* Leave off null terminator. */
1356 ret
= CFDataCreateMutable(NULL
, dst_len
);
1362 CFDataSetLength(ret
, dst_len
);
1363 dst
= (LPSTR
)CFDataGetMutableBytePtr(ret
);
1364 WideCharToMultiByte(CP_UTF8
, 0, src
, -1, dst
, dst_len
, NULL
, NULL
);
1366 /* Remove carriage returns */
1367 for (i
= 0, j
= 0; i
< dst_len
; i
++)
1369 if (dst
[i
] == '\r' &&
1370 (i
+ 1 >= dst_len
|| dst
[i
+ 1] == '\n' || dst
[i
+ 1] == '\0'))
1374 CFDataSetLength(ret
, j
);
1382 /**************************************************************************
1383 * export_unicodetext_to_utf16
1385 * Export CF_UNICODETEXT to UTF-16.
1387 static CFDataRef
export_unicodetext_to_utf16(HANDLE data
)
1389 CFMutableDataRef ret
;
1393 src
= GlobalLock(data
);
1394 if (!src
) return NULL
;
1396 src_len
= GlobalSize(data
) / sizeof(WCHAR
);
1397 if (src_len
) src_len
--; /* Leave off null terminator. */
1398 ret
= CFDataCreateMutable(NULL
, src_len
* sizeof(WCHAR
));
1404 CFDataSetLength(ret
, src_len
* sizeof(WCHAR
));
1405 dst
= (LPWSTR
)CFDataGetMutableBytePtr(ret
);
1407 /* Remove carriage returns */
1408 for (i
= 0, j
= 0; i
< src_len
; i
++)
1410 if (src
[i
] == '\r' &&
1411 (i
+ 1 >= src_len
|| src
[i
+ 1] == '\n' || src
[i
+ 1] == '\0'))
1415 CFDataSetLength(ret
, j
* sizeof(WCHAR
));
1423 /**************************************************************************
1424 * get_clipboard_info
1426 static BOOL
get_clipboard_info(LPCLIPBOARDINFO cbinfo
)
1430 SERVER_START_REQ(set_clipboard_info
)
1434 if (wine_server_call_err(req
))
1436 ERR("Failed to get clipboard owner.\n");
1440 cbinfo
->hwnd_owner
= wine_server_ptr_handle(reply
->old_owner
);
1441 cbinfo
->flags
= reply
->flags
;
1452 /**************************************************************************
1455 static BOOL
release_ownership(void)
1459 SERVER_START_REQ(set_clipboard_info
)
1461 req
->flags
= SET_CB_RELOWNER
| SET_CB_SEQNO
;
1463 if (wine_server_call_err(req
))
1464 ERR("Failed to set clipboard.\n");
1474 /**************************************************************************
1475 * macdrv_get_pasteboard_data
1477 HANDLE
macdrv_get_pasteboard_data(CFTypeRef pasteboard
, UINT desired_format
)
1482 CFStringRef type
, best_type
;
1483 WINE_CLIPFORMAT
* best_format
= NULL
;
1486 TRACE("pasteboard %p, desired_format %s\n", pasteboard
, debugstr_format(desired_format
));
1488 types
= macdrv_copy_pasteboard_types(pasteboard
);
1491 WARN("Failed to copy pasteboard types\n");
1495 count
= CFArrayGetCount(types
);
1496 TRACE("got %ld types\n", count
);
1498 for (i
= 0; (!best_format
|| best_format
->synthesized
) && i
< count
; i
++)
1500 WINE_CLIPFORMAT
* format
;
1502 type
= CFArrayGetValueAtIndex(types
, i
);
1505 while ((!best_format
|| best_format
->synthesized
) && (format
= format_for_type(format
, type
)))
1507 TRACE("for type %s got format %p/%s\n", debugstr_cf(type
), format
, debugstr_format(format
? format
->format_id
: 0));
1509 if (format
->format_id
== desired_format
)
1511 /* The best format is the matching one which is not synthesized. Failing that,
1512 the best format is the first matching synthesized format. */
1513 if (!format
->synthesized
|| !best_format
)
1516 best_format
= format
;
1524 CFDataRef pasteboard_data
= macdrv_copy_pasteboard_data(pasteboard
, best_type
);
1526 TRACE("got pasteboard data for type %s: %s\n", debugstr_cf(best_type
), debugstr_cf(pasteboard_data
));
1528 if (pasteboard_data
)
1530 data
= best_format
->import_func(pasteboard_data
);
1531 CFRelease(pasteboard_data
);
1536 TRACE(" -> %p\n", data
);
1541 /**************************************************************************
1542 * macdrv_pasteboard_has_format
1544 BOOL
macdrv_pasteboard_has_format(CFTypeRef pasteboard
, UINT desired_format
)
1551 TRACE("pasteboard %p, desired_format %s\n", pasteboard
, debugstr_format(desired_format
));
1553 types
= macdrv_copy_pasteboard_types(pasteboard
);
1556 WARN("Failed to copy pasteboard types\n");
1560 count
= CFArrayGetCount(types
);
1561 TRACE("got %d types\n", count
);
1563 for (i
= 0; !found
&& i
< count
; i
++)
1565 CFStringRef type
= CFArrayGetValueAtIndex(types
, i
);
1566 WINE_CLIPFORMAT
* format
;
1569 while (!found
&& (format
= format_for_type(format
, type
)))
1571 TRACE("for type %s got format %s\n", debugstr_cf(type
), debugstr_format(format
->format_id
));
1573 if (format
->format_id
== desired_format
)
1579 TRACE(" -> %d\n", found
);
1584 /**************************************************************************
1585 * macdrv_copy_pasteboard_formats
1587 CFArrayRef
macdrv_copy_pasteboard_formats(CFTypeRef pasteboard
)
1591 CFMutableArrayRef formats
;
1593 WINE_CLIPFORMAT
* format
;
1595 TRACE("pasteboard %p\n", pasteboard
);
1597 types
= macdrv_copy_pasteboard_types(pasteboard
);
1600 WARN("Failed to copy pasteboard types\n");
1604 count
= CFArrayGetCount(types
);
1605 TRACE("got %ld types\n", count
);
1613 formats
= CFArrayCreateMutable(NULL
, 0, NULL
);
1616 WARN("Failed to allocate formats array\n");
1621 for (i
= 0; i
< count
; i
++)
1623 CFStringRef type
= CFArrayGetValueAtIndex(types
, i
);
1627 while ((format
= format_for_type(format
, type
)))
1629 /* Suppose type is "public.utf8-plain-text". format->format_id will be each of
1630 CF_TEXT, CF_OEMTEXT, and CF_UNICODETEXT in turn. We want to look up the natural
1631 type for each of those IDs (e.g. CF_TEXT -> "org.winehq.builtin.text") and then see
1632 if that type is present in the pasteboard. If it is, then we don't want to add the
1633 format to the list yet because it would be out of order.
1635 For example, if a Mac app put "public.utf8-plain-text" and "public.tiff" on the
1636 pasteboard, then we want the Win32 clipboard formats to be CF_TEXT, CF_OEMTEXT, and
1637 CF_UNICODETEXT, and CF_TIFF, in that order. All of the text formats belong before
1638 CF_TIFF because the Mac app expressed that text was "better" than the TIFF. In
1639 this case, as soon as we encounter "public.utf8-plain-text" we should add all of
1640 the associated text format IDs.
1642 But if a Wine process put "org.winehq.builtin.unicodetext",
1643 "public.utf8-plain-text", "public.utf16-plain-text", and "public.tiff", then we
1644 want the clipboard formats to be CF_UNICODETEXT, CF_TIFF, CF_TEXT, and CF_OEMTEXT,
1645 in that order. The Windows program presumably added CF_UNICODETEXT and CF_TIFF.
1646 We're synthesizing CF_TEXT and CF_OEMTEXT from CF_UNICODETEXT but we want them to
1647 come after the non-synthesized CF_TIFF. In this case, we don't want to add the
1648 text formats upon encountering "public.utf8-plain-text",
1650 We tell the two cases apart by seeing that one of the natural types for the text
1651 formats (i.e. "org.winehq.builtin.unicodetext") is present on the pasteboard.
1652 "found" indicates that. */
1654 if (!format
->synthesized
)
1656 TRACE("for type %s got primary format %p/%s\n", debugstr_cf(type
), format
, debugstr_format(format
->format_id
));
1657 CFArrayAppendValue(formats
, (void*)format
->format_id
);
1660 else if (!found
&& format
->natural_format
&&
1661 CFArrayContainsValue(types
, CFRangeMake(0, count
), format
->natural_format
->type
))
1663 TRACE("for type %s deferring synthesized formats because type %s is also present\n",
1664 debugstr_cf(type
), debugstr_cf(format
->natural_format
->type
));
1671 while ((format
= format_for_type(format
, type
)))
1673 /* Don't override a real value with a synthesized value. */
1674 if (!CFArrayContainsValue(formats
, CFRangeMake(0, CFArrayGetCount(formats
)), (void*)format
->format_id
))
1676 TRACE("for type %s got synthesized format %p/%s\n", debugstr_cf(type
), format
, debugstr_format(format
->format_id
));
1677 CFArrayAppendValue(formats
, (void*)format
->format_id
);
1683 /* Now go back through the types adding the synthesized formats that we deferred before. */
1684 for (i
= 0; i
< count
; i
++)
1686 CFStringRef type
= CFArrayGetValueAtIndex(types
, i
);
1689 while ((format
= format_for_type(format
, type
)))
1691 if (format
->synthesized
)
1693 /* Don't override a real value with a synthesized value. */
1694 if (!CFArrayContainsValue(formats
, CFRangeMake(0, CFArrayGetCount(formats
)), (void*)format
->format_id
))
1696 TRACE("for type %s got synthesized format %p/%s\n", debugstr_cf(type
), format
, debugstr_format(format
->format_id
));
1697 CFArrayAppendValue(formats
, (void*)format
->format_id
);
1705 TRACE(" -> %s\n", debugstr_cf(formats
));
1710 /**************************************************************************
1711 * check_clipboard_ownership
1713 static void check_clipboard_ownership(HWND
*owner
)
1715 CLIPBOARDINFO cbinfo
;
1717 if (owner
) *owner
= NULL
;
1719 /* If Wine thinks we're the clipboard owner but Mac OS X thinks we're not
1720 the pasteboard owner, update Wine. */
1721 if (get_clipboard_info(&cbinfo
) && (cbinfo
.flags
& CB_PROCESS
))
1723 if (!(cbinfo
.flags
& CB_OPEN
) && !macdrv_is_pasteboard_owner())
1725 TRACE("Lost clipboard ownership\n");
1727 if (OpenClipboard(cbinfo
.hwnd_owner
))
1729 /* Destroy private objects */
1730 SendMessageW(cbinfo
.hwnd_owner
, WM_DESTROYCLIPBOARD
, 0, 0);
1732 /* Give up ownership of the windows clipboard */
1733 release_ownership();
1738 *owner
= cbinfo
.hwnd_owner
;
1743 /**************************************************************************
1744 * Mac User Driver Clipboard Exports
1745 **************************************************************************/
1748 /**************************************************************************
1749 * CountClipboardFormats (MACDRV.@)
1751 INT CDECL
macdrv_CountClipboardFormats(void)
1753 CFMutableSetRef seen_formats
;
1760 check_clipboard_ownership(NULL
);
1762 seen_formats
= CFSetCreateMutable(NULL
, 0, NULL
);
1765 WARN("Failed to allocate set to track seen formats\n");
1769 types
= macdrv_copy_pasteboard_types(NULL
);
1772 WARN("Failed to copy pasteboard types\n");
1773 CFRelease(seen_formats
);
1777 count
= CFArrayGetCount(types
);
1778 TRACE("got %ld types\n", count
);
1780 for (i
= 0; i
< count
; i
++)
1782 CFStringRef type
= CFArrayGetValueAtIndex(types
, i
);
1783 WINE_CLIPFORMAT
* format
;
1786 while ((format
= format_for_type(format
, type
)))
1788 TRACE("for type %s got format %p/%s\n", debugstr_cf(type
), format
, debugstr_format(format
->format_id
));
1790 if (!CFSetContainsValue(seen_formats
, (void*)format
->format_id
))
1793 CFSetAddValue(seen_formats
, (void*)format
->format_id
);
1799 CFRelease(seen_formats
);
1800 TRACE(" -> %d\n", ret
);
1805 /**************************************************************************
1806 * EmptyClipboard (MACDRV.@)
1808 * Empty cached clipboard data.
1810 void CDECL
macdrv_EmptyClipboard(void)
1813 check_clipboard_ownership(NULL
);
1814 macdrv_clear_pasteboard();
1818 /**************************************************************************
1819 * EndClipboardUpdate (MACDRV.@)
1821 void CDECL
macdrv_EndClipboardUpdate(void)
1824 check_clipboard_ownership(NULL
);
1828 /**************************************************************************
1829 * EnumClipboardFormats (MACDRV.@)
1831 UINT CDECL
macdrv_EnumClipboardFormats(UINT prev_format
)
1838 TRACE("prev_format %s\n", debugstr_format(prev_format
));
1839 check_clipboard_ownership(NULL
);
1841 formats
= macdrv_copy_pasteboard_formats(NULL
);
1844 count
= CFArrayGetCount(formats
);
1847 i
= CFArrayGetFirstIndexOfValue(formats
, CFRangeMake(0, count
), (void*)prev_format
);
1848 if (i
!= kCFNotFound
)
1854 if (i
!= kCFNotFound
&& i
< count
)
1855 ret
= (UINT
)CFArrayGetValueAtIndex(formats
, i
);
1860 TRACE(" -> %u\n", ret
);
1865 /**************************************************************************
1866 * GetClipboardData (MACDRV.@)
1868 HANDLE CDECL
macdrv_GetClipboardData(UINT desired_format
)
1870 check_clipboard_ownership(NULL
);
1872 return macdrv_get_pasteboard_data(NULL
, desired_format
);
1876 /**************************************************************************
1877 * IsClipboardFormatAvailable (MACDRV.@)
1879 BOOL CDECL
macdrv_IsClipboardFormatAvailable(UINT desired_format
)
1881 check_clipboard_ownership(NULL
);
1882 return macdrv_pasteboard_has_format(NULL
, desired_format
);
1886 /**************************************************************************
1887 * SetClipboardData (MACDRV.@)
1889 BOOL CDECL
macdrv_SetClipboardData(UINT format_id
, HANDLE data
, BOOL owner
)
1892 macdrv_window window
;
1893 WINE_CLIPFORMAT
*format
;
1894 CFDataRef cfdata
= NULL
;
1896 check_clipboard_ownership(&hwnd_owner
);
1897 window
= macdrv_get_cocoa_window(GetAncestor(hwnd_owner
, GA_ROOT
), FALSE
);
1898 TRACE("format_id %s data %p owner %d hwnd_owner %p window %p)\n", debugstr_format(format_id
), data
, owner
, hwnd_owner
, window
);
1900 format
= natural_format_for_format(format_id
);
1901 if (!format
&& !(format
= insert_clipboard_format(format_id
, NULL
)))
1903 WARN("Failed to register clipboard format %s\n", debugstr_format(format_id
));
1907 /* Export the data to the Mac pasteboard. */
1910 if (!format
->export_func
|| !(cfdata
= format
->export_func(data
)))
1912 WARN("Failed to export %s data to type %s\n", debugstr_format(format_id
), debugstr_cf(format
->type
));
1917 if (macdrv_set_pasteboard_data(format
->type
, cfdata
, window
))
1918 TRACE("Set pasteboard data for type %s: %s\n", debugstr_cf(format
->type
), debugstr_cf(cfdata
));
1921 WARN("Failed to set pasteboard data for type %s: %s\n", debugstr_cf(format
->type
), debugstr_cf(cfdata
));
1922 if (cfdata
) CFRelease(cfdata
);
1926 if (cfdata
) CFRelease(cfdata
);
1928 /* Find any other formats for this format_id (the exportable synthesized ones). */
1929 LIST_FOR_EACH_ENTRY(format
, &format_list
, WINE_CLIPFORMAT
, entry
)
1931 if (format
->format_id
== format_id
&& format
->synthesized
&& format
->export_func
)
1933 /* We have a synthesized format for this format ID. Add its type to the pasteboard. */
1934 TRACE("Synthesized from format %s: type %s\n", debugstr_format(format_id
), debugstr_cf(format
->type
));
1938 cfdata
= format
->export_func(data
);
1941 WARN("Failed to export %s data to type %s\n", debugstr_format(format
->format_id
), debugstr_cf(format
->type
));
1948 if (macdrv_set_pasteboard_data(format
->type
, cfdata
, window
))
1949 TRACE(" ... set pasteboard data: %s\n", debugstr_cf(cfdata
));
1951 WARN(" ... failed to set pasteboard data: %s\n", debugstr_cf(cfdata
));
1953 if (cfdata
) CFRelease(cfdata
);
1959 /* FIXME: According to MSDN, the caller is entitled to lock and read from
1960 data until CloseClipboard is called. So, we should defer this cleanup. */
1961 if ((format_id
>= CF_GDIOBJFIRST
&& format_id
<= CF_GDIOBJLAST
) ||
1962 format_id
== CF_BITMAP
||
1963 format_id
== CF_DIB
||
1964 format_id
== CF_PALETTE
)
1968 else if (format_id
== CF_METAFILEPICT
)
1970 DeleteMetaFile(((METAFILEPICT
*)GlobalLock(data
))->hMF
);
1973 else if (format_id
== CF_ENHMETAFILE
)
1975 DeleteEnhMetaFile(data
);
1977 else if (format_id
< CF_PRIVATEFIRST
|| CF_PRIVATELAST
< format_id
)
1987 /**************************************************************************
1988 * MACDRV Private Clipboard Exports
1989 **************************************************************************/
1992 /**************************************************************************
1993 * macdrv_clipboard_process_attach
1995 void macdrv_clipboard_process_attach(void)
1998 WINE_CLIPFORMAT
*format
;
2000 /* Register built-in formats */
2001 for (i
= 0; i
< sizeof(builtin_format_ids
)/sizeof(builtin_format_ids
[0]); i
++)
2003 if (!(format
= HeapAlloc(GetProcessHeap(), 0, sizeof(*format
)))) break;
2004 format
->format_id
= builtin_format_ids
[i
].id
;
2005 format
->type
= CFRetain(builtin_format_ids
[i
].type
);
2006 format
->import_func
= builtin_format_ids
[i
].import
;
2007 format
->export_func
= builtin_format_ids
[i
].export
;
2008 format
->synthesized
= builtin_format_ids
[i
].synthesized
;
2009 format
->natural_format
= NULL
;
2010 list_add_tail(&format_list
, &format
->entry
);
2013 LIST_FOR_EACH_ENTRY(format
, &format_list
, WINE_CLIPFORMAT
, entry
)
2015 if (format
->synthesized
)
2016 format
->natural_format
= natural_format_for_format(format
->format_id
);
2019 /* Register known mappings between Windows formats and Mac types */
2020 for (i
= 0; i
< sizeof(builtin_format_names
)/sizeof(builtin_format_names
[0]); i
++)
2022 if (!(format
= HeapAlloc(GetProcessHeap(), 0, sizeof(*format
)))) break;
2023 format
->format_id
= RegisterClipboardFormatW(builtin_format_names
[i
].name
);
2024 format
->type
= CFRetain(builtin_format_names
[i
].type
);
2025 format
->import_func
= builtin_format_names
[i
].import
;
2026 format
->export_func
= builtin_format_names
[i
].export
;
2027 format
->synthesized
= FALSE
;
2028 format
->natural_format
= NULL
;
2029 list_add_tail(&format_list
, &format
->entry
);
2034 /**************************************************************************
2035 * query_pasteboard_data
2037 BOOL
query_pasteboard_data(HWND hwnd
, CFStringRef type
)
2040 CLIPBOARDINFO cbinfo
;
2041 WINE_CLIPFORMAT
* format
;
2042 CFArrayRef types
= NULL
;
2045 TRACE("hwnd %p type %s\n", hwnd
, debugstr_cf(type
));
2047 if (get_clipboard_info(&cbinfo
))
2048 hwnd
= cbinfo
.hwnd_owner
;
2051 while ((format
= format_for_type(format
, type
)))
2053 TRACE("for type %s got format %p/%s\n", debugstr_cf(type
), format
, debugstr_format(format
->format_id
));
2055 if (!format
->synthesized
)
2057 TRACE("Sending WM_RENDERFORMAT message for format %s to hwnd %p\n", debugstr_format(format
->format_id
), hwnd
);
2058 SendMessageW(hwnd
, WM_RENDERFORMAT
, format
->format_id
, 0);
2065 types
= macdrv_copy_pasteboard_types(NULL
);
2068 WARN("Failed to copy pasteboard types\n");
2072 range
= CFRangeMake(0, CFArrayGetCount(types
));
2075 /* The type maps to a synthesized format. Now look up what type that format maps to natively
2076 (not synthesized). For example, if type is "public.utf8-plain-text", then this format may
2077 have an ID of CF_TEXT. From CF_TEXT, we want to find "org.winehq.builtin.text" to see if
2078 that type is present in the pasteboard. If it is, then the app must have promised it and
2079 we can ask it to render it. (If it had put it on the clipboard immediately, then the
2080 pasteboard would also have data for "public.utf8-plain-text" and we wouldn't be here.) If
2081 "org.winehq.builtin.text" is not on the pasteboard, then one of the other text formats is
2082 presumably responsible for the promise that we're trying to satisfy, so we keep looking. */
2083 if (format
->natural_format
&& CFArrayContainsValue(types
, range
, format
->natural_format
->type
))
2085 TRACE("Sending WM_RENDERFORMAT message for format %s to hwnd %p\n", debugstr_format(format
->format_id
), hwnd
);
2086 SendMessageW(hwnd
, WM_RENDERFORMAT
, format
->format_id
, 0);
2093 if (types
) CFRelease(types
);