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_enhmetafile_to_metafilepict(CFDataRef data
);
78 static HANDLE
import_metafilepict(CFDataRef data
);
79 static HANDLE
import_metafilepict_to_enhmetafile(CFDataRef data
);
80 static HANDLE
import_nsfilenames_to_hdrop(CFDataRef data
);
81 static HANDLE
import_oemtext_to_text(CFDataRef data
);
82 static HANDLE
import_oemtext_to_unicodetext(CFDataRef data
);
83 static HANDLE
import_text_to_oemtext(CFDataRef data
);
84 static HANDLE
import_text_to_unicodetext(CFDataRef data
);
85 static HANDLE
import_unicodetext_to_oemtext(CFDataRef data
);
86 static HANDLE
import_unicodetext_to_text(CFDataRef data
);
87 static HANDLE
import_utf8_to_oemtext(CFDataRef data
);
88 static HANDLE
import_utf8_to_text(CFDataRef data
);
89 static HANDLE
import_utf8_to_unicodetext(CFDataRef data
);
90 static HANDLE
import_utf16_to_oemtext(CFDataRef data
);
91 static HANDLE
import_utf16_to_text(CFDataRef data
);
92 static HANDLE
import_utf16_to_unicodetext(CFDataRef data
);
94 static CFDataRef
export_clipboard_data(HANDLE data
);
95 static CFDataRef
export_bitmap_to_bmp(HANDLE data
);
96 static CFDataRef
export_dib_to_bmp(HANDLE data
);
97 static CFDataRef
export_enhmetafile(HANDLE data
);
98 static CFDataRef
export_hdrop_to_filenames(HANDLE data
);
99 static CFDataRef
export_metafilepict(HANDLE data
);
100 static CFDataRef
export_oemtext_to_utf8(HANDLE data
);
101 static CFDataRef
export_oemtext_to_utf16(HANDLE data
);
102 static CFDataRef
export_text_to_utf8(HANDLE data
);
103 static CFDataRef
export_text_to_utf16(HANDLE data
);
104 static CFDataRef
export_unicodetext_to_utf8(HANDLE data
);
105 static CFDataRef
export_unicodetext_to_utf16(HANDLE data
);
108 /**************************************************************************
110 **************************************************************************/
112 /* Clipboard formats */
113 static struct list format_list
= LIST_INIT(format_list
);
115 /* There are two naming schemes involved and we want to have a mapping between
116 them. There are Win32 clipboard format names and there are Mac pasteboard
119 The Win32 standard clipboard formats don't have names, but they are associated
120 with Mac pasteboard types through the following tables, which are used to
121 initialize the format_list. Where possible, the standard clipboard formats
122 are mapped to predefined pasteboard type UTIs. Otherwise, we create Wine-
123 specific types of the form "org.winehq.builtin.<format>", where <format> is
124 the name of the symbolic constant for the format minus "CF_" and lowercased.
125 E.g. CF_BITMAP -> org.winehq.builtin.bitmap.
127 Win32 clipboard formats which originate in a Windows program may be registered
128 with an arbitrary name. We construct a Mac pasteboard type from these by
129 prepending "org.winehq.registered." to the registered name.
131 Likewise, Mac pasteboard types which originate in other apps may have
132 arbitrary type strings. We ignore these.
135 Win32 clipboard format names:
136 <none> standard clipboard format; maps via
137 format_list to either a predefined Mac UTI
138 or org.winehq.builtin.<format>.
139 <other> name registered within Win32 land; maps to
140 org.winehq.registered.<other>
141 Mac pasteboard type names:
142 org.winehq.builtin.<format ID> representation of Win32 standard clipboard
143 format for which there was no corresponding
144 predefined Mac UTI; maps via format_list
145 org.winehq.registered.<format name> representation of Win32 registered
146 clipboard format name; maps to <format name>
147 <other> Mac pasteboard type originating with system
148 or other apps; either maps via format_list
149 to a standard clipboard format or ignored
156 DRVIMPORTFUNC import
;
157 DRVEXPORTFUNC export
;
159 } builtin_format_ids
[] =
161 { CF_DIBV5
, CFSTR("org.winehq.builtin.dibv5"), import_clipboard_data
, export_clipboard_data
, FALSE
},
162 { CF_DIF
, CFSTR("org.winehq.builtin.dif"), import_clipboard_data
, export_clipboard_data
, FALSE
},
163 { CF_DSPBITMAP
, CFSTR("org.winehq.builtin.dspbitmap"), import_clipboard_data
, export_clipboard_data
, FALSE
},
164 { CF_DSPENHMETAFILE
, CFSTR("org.winehq.builtin.dspenhmetafile"), import_clipboard_data
, export_clipboard_data
, FALSE
},
165 { CF_DSPMETAFILEPICT
, CFSTR("org.winehq.builtin.dspmetafilepict"), import_clipboard_data
, export_clipboard_data
, FALSE
},
166 { CF_DSPTEXT
, CFSTR("org.winehq.builtin.dsptext"), import_clipboard_data
, export_clipboard_data
, FALSE
},
167 { CF_LOCALE
, CFSTR("org.winehq.builtin.locale"), import_clipboard_data
, export_clipboard_data
, FALSE
},
168 { CF_OWNERDISPLAY
, CFSTR("org.winehq.builtin.ownerdisplay"), import_clipboard_data
, export_clipboard_data
, FALSE
},
169 { CF_PALETTE
, CFSTR("org.winehq.builtin.palette"), import_clipboard_data
, export_clipboard_data
, FALSE
},
170 { CF_PENDATA
, CFSTR("org.winehq.builtin.pendata"), import_clipboard_data
, export_clipboard_data
, FALSE
},
171 { CF_RIFF
, CFSTR("org.winehq.builtin.riff"), import_clipboard_data
, export_clipboard_data
, FALSE
},
172 { CF_SYLK
, CFSTR("org.winehq.builtin.sylk"), import_clipboard_data
, export_clipboard_data
, FALSE
},
173 { CF_TIFF
, CFSTR("public.tiff"), import_clipboard_data
, export_clipboard_data
, FALSE
},
174 { CF_WAVE
, CFSTR("com.microsoft.waveform-audio"), import_clipboard_data
, export_clipboard_data
, FALSE
},
176 { CF_UNICODETEXT
, CFSTR("org.winehq.builtin.unicodetext"), import_clipboard_data
, export_clipboard_data
, FALSE
},
177 { CF_TEXT
, CFSTR("org.winehq.builtin.unicodetext"), import_unicodetext_to_text
, NULL
, TRUE
},
178 { CF_OEMTEXT
, CFSTR("org.winehq.builtin.unicodetext"), import_unicodetext_to_oemtext
, NULL
, TRUE
},
180 { CF_TEXT
, CFSTR("org.winehq.builtin.text"), import_clipboard_data
, export_clipboard_data
, FALSE
},
181 { CF_OEMTEXT
, CFSTR("org.winehq.builtin.text"), import_text_to_oemtext
, NULL
, TRUE
},
182 { CF_UNICODETEXT
, CFSTR("org.winehq.builtin.text"), import_text_to_unicodetext
, NULL
, TRUE
},
184 { CF_OEMTEXT
, CFSTR("org.winehq.builtin.oemtext"), import_clipboard_data
, export_clipboard_data
, FALSE
},
185 { CF_TEXT
, CFSTR("org.winehq.builtin.oemtext"), import_oemtext_to_text
, NULL
, TRUE
},
186 { CF_UNICODETEXT
, CFSTR("org.winehq.builtin.oemtext"), import_oemtext_to_unicodetext
, NULL
, TRUE
},
188 { CF_TEXT
, CFSTR("public.utf8-plain-text"), import_utf8_to_text
, export_text_to_utf8
, TRUE
},
189 { CF_OEMTEXT
, CFSTR("public.utf8-plain-text"), import_utf8_to_oemtext
, export_oemtext_to_utf8
, TRUE
},
190 { CF_UNICODETEXT
, CFSTR("public.utf8-plain-text"), import_utf8_to_unicodetext
, export_unicodetext_to_utf8
, TRUE
},
192 { CF_TEXT
, CFSTR("public.utf16-plain-text"), import_utf16_to_text
, export_text_to_utf16
, TRUE
},
193 { CF_OEMTEXT
, CFSTR("public.utf16-plain-text"), import_utf16_to_oemtext
, export_oemtext_to_utf16
, TRUE
},
194 { CF_UNICODETEXT
, CFSTR("public.utf16-plain-text"), import_utf16_to_unicodetext
, export_unicodetext_to_utf16
,TRUE
},
196 { CF_DIB
, CFSTR("org.winehq.builtin.dib"), import_clipboard_data
, export_clipboard_data
, FALSE
},
197 { CF_DIB
, CFSTR("com.microsoft.bmp"), import_bmp_to_dib
, export_dib_to_bmp
, TRUE
},
199 { CF_BITMAP
, CFSTR("org.winehq.builtin.bitmap"), import_bmp_to_bitmap
, export_bitmap_to_bmp
, FALSE
},
200 { CF_BITMAP
, CFSTR("com.microsoft.bmp"), import_bmp_to_bitmap
, export_bitmap_to_bmp
, TRUE
},
202 { CF_HDROP
, CFSTR("org.winehq.builtin.hdrop"), import_clipboard_data
, export_clipboard_data
, FALSE
},
203 { CF_HDROP
, CFSTR("NSFilenamesPboardType"), import_nsfilenames_to_hdrop
, export_hdrop_to_filenames
, TRUE
},
205 { CF_ENHMETAFILE
, CFSTR("org.winehq.builtin.enhmetafile"), import_enhmetafile
, export_enhmetafile
, FALSE
},
206 { CF_METAFILEPICT
, CFSTR("org.winehq.builtin.enhmetafile"), import_enhmetafile_to_metafilepict
, NULL
, TRUE
},
208 { CF_METAFILEPICT
, CFSTR("org.winehq.builtin.metafilepict"), import_metafilepict
, export_metafilepict
, FALSE
},
209 { CF_ENHMETAFILE
, CFSTR("org.winehq.builtin.metafilepict"), import_metafilepict_to_enhmetafile
, NULL
, TRUE
},
212 static const WCHAR wszRichTextFormat
[] = {'R','i','c','h',' ','T','e','x','t',' ','F','o','r','m','a','t',0};
213 static const WCHAR wszGIF
[] = {'G','I','F',0};
214 static const WCHAR wszJFIF
[] = {'J','F','I','F',0};
215 static const WCHAR wszPNG
[] = {'P','N','G',0};
216 static const WCHAR wszHTMLFormat
[] = {'H','T','M','L',' ','F','o','r','m','a','t',0};
221 DRVIMPORTFUNC import
;
222 DRVEXPORTFUNC export
;
223 } builtin_format_names
[] =
225 { wszRichTextFormat
, CFSTR("public.rtf"), import_clipboard_data
, export_clipboard_data
},
226 { wszGIF
, CFSTR("com.compuserve.gif"), import_clipboard_data
, export_clipboard_data
},
227 { wszJFIF
, CFSTR("public.jpeg"), import_clipboard_data
, export_clipboard_data
},
228 { wszPNG
, CFSTR("public.png"), import_clipboard_data
, export_clipboard_data
},
229 { wszHTMLFormat
, CFSTR("public.html"), import_clipboard_data
, export_clipboard_data
},
230 { CFSTR_SHELLURLW
, CFSTR("public.url"), import_utf8_to_text
, export_text_to_utf8
},
233 /* The prefix prepended to a Win32 clipboard format name to make a Mac pasteboard type. */
234 static const CFStringRef registered_name_type_prefix
= CFSTR("org.winehq.registered.");
237 /**************************************************************************
238 * Internal Clipboard implementation methods
239 **************************************************************************/
242 * format_list functions
245 /**************************************************************************
248 const char *debugstr_format(UINT id
)
252 if (GetClipboardFormatNameW(id
, buffer
, 256))
253 return wine_dbg_sprintf("0x%04x %s", id
, debugstr_w(buffer
));
257 #define BUILTIN(id) case id: return #id;
260 BUILTIN(CF_METAFILEPICT
)
270 BUILTIN(CF_UNICODETEXT
)
271 BUILTIN(CF_ENHMETAFILE
)
275 BUILTIN(CF_OWNERDISPLAY
)
277 BUILTIN(CF_DSPBITMAP
)
278 BUILTIN(CF_DSPMETAFILEPICT
)
279 BUILTIN(CF_DSPENHMETAFILE
)
281 default: return wine_dbg_sprintf("0x%04x", id
);
286 /**************************************************************************
287 * insert_clipboard_format
289 static WINE_CLIPFORMAT
*insert_clipboard_format(UINT id
, CFStringRef type
)
291 WINE_CLIPFORMAT
*format
;
293 format
= HeapAlloc(GetProcessHeap(), 0, sizeof(*format
));
297 WARN("No more memory for a new format!\n");
300 format
->format_id
= id
;
301 format
->import_func
= import_clipboard_data
;
302 format
->export_func
= export_clipboard_data
;
303 format
->synthesized
= FALSE
;
304 format
->natural_format
= NULL
;
307 format
->type
= CFStringCreateCopy(NULL
, type
);
312 if (!GetClipboardFormatNameW(format
->format_id
, buffer
, sizeof(buffer
) / sizeof(buffer
[0])))
314 WARN("failed to get name for format %s; error 0x%08x\n", debugstr_format(format
->format_id
), GetLastError());
315 HeapFree(GetProcessHeap(), 0, format
);
319 format
->type
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@%S"),
320 registered_name_type_prefix
, buffer
);
323 list_add_tail(&format_list
, &format
->entry
);
325 TRACE("Registering format %s type %s\n", debugstr_format(format
->format_id
),
326 debugstr_cf(format
->type
));
332 /**************************************************************************
335 * Register a custom Mac clipboard format.
337 static WINE_CLIPFORMAT
* register_format(UINT id
, CFStringRef type
)
339 WINE_CLIPFORMAT
*format
;
341 /* walk format chain to see if it's already registered */
342 LIST_FOR_EACH_ENTRY(format
, &format_list
, WINE_CLIPFORMAT
, entry
)
343 if (format
->format_id
== id
) return format
;
345 return insert_clipboard_format(id
, type
);
349 /**************************************************************************
352 static WINE_CLIPFORMAT
* format_for_type(WINE_CLIPFORMAT
*current
, CFStringRef type
)
354 struct list
*ptr
= current
? ¤t
->entry
: &format_list
;
355 WINE_CLIPFORMAT
*format
= NULL
;
357 TRACE("current %p/%s type %s\n", current
, debugstr_format(current
? current
->format_id
: 0), debugstr_cf(type
));
359 while ((ptr
= list_next(&format_list
, ptr
)))
361 format
= LIST_ENTRY(ptr
, WINE_CLIPFORMAT
, entry
);
362 if (CFEqual(format
->type
, type
))
369 if (CFStringHasPrefix(type
, CFSTR("org.winehq.builtin.")))
371 ERR("Shouldn't happen. Built-in type %s should have matched something in format list.\n",
374 else if (CFStringHasPrefix(type
, registered_name_type_prefix
))
377 int len
= CFStringGetLength(type
) - CFStringGetLength(registered_name_type_prefix
);
379 name
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
));
380 CFStringGetCharacters(type
, CFRangeMake(CFStringGetLength(registered_name_type_prefix
), len
),
384 format
= register_format(RegisterClipboardFormatW(name
), type
);
386 ERR("Failed to register format for type %s name %s\n", debugstr_cf(type
), debugstr_w(name
));
388 HeapFree(GetProcessHeap(), 0, name
);
393 TRACE(" -> %p/%s\n", format
, debugstr_format(format
? format
->format_id
: 0));
398 /**************************************************************************
399 * natural_format_for_format
401 * Find the "natural" format for this format_id (the one which isn't
402 * synthesized from another type).
404 static WINE_CLIPFORMAT
* natural_format_for_format(UINT format_id
)
406 WINE_CLIPFORMAT
*format
;
408 LIST_FOR_EACH_ENTRY(format
, &format_list
, WINE_CLIPFORMAT
, entry
)
409 if (format
->format_id
== format_id
&& !format
->synthesized
) break;
411 if (&format
->entry
== &format_list
)
414 TRACE("%s -> %p/%s\n", debugstr_format(format_id
), format
, debugstr_cf(format
? format
->type
: NULL
));
419 /**************************************************************************
422 * Convert string data between code pages or to/from wide characters. The
423 * special value of (UINT)-1 for a code page indicates to use wide
426 static HANDLE
convert_text(const void *src
, int src_len
, UINT src_cp
, UINT dest_cp
)
434 if (src_cp
== (UINT
)-1)
437 wstr_len
= src_len
/ sizeof(WCHAR
);
443 wstr_len
= MultiByteToWideChar(src_cp
, 0, src
, src_len
, NULL
, 0);
444 if (!src_len
|| ((const char*)src
)[src_len
- 1]) wstr_len
+= 1;
445 temp
= HeapAlloc(GetProcessHeap(), 0, wstr_len
* sizeof(WCHAR
));
446 MultiByteToWideChar(src_cp
, 0, src
, src_len
, temp
, wstr_len
);
447 temp
[wstr_len
- 1] = 0;
451 if (dest_cp
== (UINT
)-1)
453 handle
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, wstr_len
* sizeof(WCHAR
));
454 if (handle
&& (p
= GlobalLock(handle
)))
456 memcpy(p
, wstr
, wstr_len
* sizeof(WCHAR
));
457 GlobalUnlock(handle
);
465 len
= WideCharToMultiByte(dest_cp
, 0, wstr
, wstr_len
, NULL
, 0, NULL
, NULL
);
466 if (!wstr_len
|| wstr
[wstr_len
- 1]) len
+= 1;
467 handle
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, len
);
469 if (handle
&& (p
= GlobalLock(handle
)))
471 WideCharToMultiByte(dest_cp
, 0, wstr
, wstr_len
, p
, len
, NULL
, NULL
);
473 GlobalUnlock(handle
);
482 /**************************************************************************
483 * convert_unicodetext_to_codepage
485 static HANDLE
convert_unicodetext_to_codepage(HANDLE unicode_handle
, UINT cp
)
487 LPWSTR unicode_string
= GlobalLock(unicode_handle
);
492 ret
= convert_text(unicode_string
, GlobalSize(unicode_handle
), -1, cp
);
493 GlobalUnlock(unicode_handle
);
500 /***********************************************************************
503 * Return the size of the bitmap info structure including color table.
505 static int bitmap_info_size(const BITMAPINFO
*info
, WORD coloruse
)
507 unsigned int colors
, size
, masks
= 0;
509 if (info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
511 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)info
;
512 colors
= (core
->bcBitCount
<= 8) ? 1 << core
->bcBitCount
: 0;
513 return sizeof(BITMAPCOREHEADER
) + colors
*
514 ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBTRIPLE
) : sizeof(WORD
));
516 else /* assume BITMAPINFOHEADER */
518 colors
= info
->bmiHeader
.biClrUsed
;
519 if (!colors
&& (info
->bmiHeader
.biBitCount
<= 8))
520 colors
= 1 << info
->bmiHeader
.biBitCount
;
521 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
) masks
= 3;
522 size
= max(info
->bmiHeader
.biSize
, sizeof(BITMAPINFOHEADER
) + masks
* sizeof(DWORD
));
523 return size
+ colors
* ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBQUAD
) : sizeof(WORD
));
528 /***********************************************************************
529 * create_dib_from_bitmap
531 * Allocates a packed DIB and copies the bitmap data into it.
533 static HGLOBAL
create_dib_from_bitmap(HBITMAP hBmp
)
539 LPBITMAPINFOHEADER pbmiHeader
;
540 unsigned int cDataSize
, cPackedSize
, OffsetBits
;
543 if (!GetObjectW(hBmp
, sizeof(bmp
), &bmp
)) return 0;
546 * A packed DIB contains a BITMAPINFO structure followed immediately by
547 * an optional color palette and the pixel data.
550 /* Calculate the size of the packed DIB */
551 cDataSize
= abs(bmp
.bmHeight
) * (((bmp
.bmWidth
* bmp
.bmBitsPixel
+ 31) / 8) & ~3);
552 cPackedSize
= sizeof(BITMAPINFOHEADER
)
553 + ((bmp
.bmBitsPixel
<= 8) ? (sizeof(RGBQUAD
) * (1 << bmp
.bmBitsPixel
)) : 0)
555 /* Get the offset to the bits */
556 OffsetBits
= cPackedSize
- cDataSize
;
558 /* Allocate the packed DIB */
559 TRACE("\tAllocating packed DIB of size %d\n", cPackedSize
);
560 hPackedDIB
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, cPackedSize
);
563 WARN("Could not allocate packed DIB!\n");
567 /* A packed DIB starts with a BITMAPINFOHEADER */
568 pPackedDIB
= GlobalLock(hPackedDIB
);
569 pbmiHeader
= (LPBITMAPINFOHEADER
)pPackedDIB
;
571 /* Init the BITMAPINFOHEADER */
572 pbmiHeader
->biSize
= sizeof(BITMAPINFOHEADER
);
573 pbmiHeader
->biWidth
= bmp
.bmWidth
;
574 pbmiHeader
->biHeight
= bmp
.bmHeight
;
575 pbmiHeader
->biPlanes
= 1;
576 pbmiHeader
->biBitCount
= bmp
.bmBitsPixel
;
577 pbmiHeader
->biCompression
= BI_RGB
;
578 pbmiHeader
->biSizeImage
= 0;
579 pbmiHeader
->biXPelsPerMeter
= pbmiHeader
->biYPelsPerMeter
= 0;
580 pbmiHeader
->biClrUsed
= 0;
581 pbmiHeader
->biClrImportant
= 0;
583 /* Retrieve the DIB bits from the bitmap and fill in the
584 * DIB color table if present */
586 nLinesCopied
= GetDIBits(hdc
, /* Handle to device context */
587 hBmp
, /* Handle to bitmap */
588 0, /* First scan line to set in dest bitmap */
589 bmp
.bmHeight
, /* Number of scan lines to copy */
590 pPackedDIB
+ OffsetBits
, /* [out] Address of array for bitmap bits */
591 (LPBITMAPINFO
) pbmiHeader
, /* [out] Address of BITMAPINFO structure */
592 0); /* RGB or palette index */
593 GlobalUnlock(hPackedDIB
);
596 /* Cleanup if GetDIBits failed */
597 if (nLinesCopied
!= bmp
.bmHeight
)
599 TRACE("\tGetDIBits returned %d. Actual lines=%d\n", nLinesCopied
, bmp
.bmHeight
);
600 GlobalFree(hPackedDIB
);
607 /**************************************************************************
608 * import_clipboard_data
610 * Generic import clipboard data routine.
612 static HANDLE
import_clipboard_data(CFDataRef data
)
614 HANDLE data_handle
= NULL
;
616 size_t len
= CFDataGetLength(data
);
621 /* Turn on the DDESHARE flag to enable shared 32 bit memory */
622 data_handle
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, len
);
626 if ((p
= GlobalLock(data_handle
)))
628 memcpy(p
, CFDataGetBytePtr(data
), len
);
629 GlobalUnlock(data_handle
);
633 GlobalFree(data_handle
);
642 /**************************************************************************
643 * import_bmp_to_bitmap
645 * Import BMP data, converting to CF_BITMAP format.
647 static HANDLE
import_bmp_to_bitmap(CFDataRef data
)
650 HANDLE dib
= import_bmp_to_dib(data
);
653 if (dib
&& (bmi
= GlobalLock(dib
)))
660 offset
= bitmap_info_size(bmi
, DIB_RGB_COLORS
);
662 ret
= CreateDIBitmap(hdc
, &bmi
->bmiHeader
, CBM_INIT
, (LPBYTE
)bmi
+ offset
,
663 bmi
, DIB_RGB_COLORS
);
666 ReleaseDC(NULL
, hdc
);
674 /**************************************************************************
677 * Import BMP data, converting to CF_DIB format. This just entails
678 * stripping the BMP file format header.
680 static HANDLE
import_bmp_to_dib(CFDataRef data
)
683 BITMAPFILEHEADER
*bfh
= (BITMAPFILEHEADER
*)CFDataGetBytePtr(data
);
684 CFIndex len
= CFDataGetLength(data
);
686 if (len
>= sizeof(*bfh
) + sizeof(BITMAPCOREHEADER
) &&
687 bfh
->bfType
== 0x4d42 /* "BM" */)
689 BITMAPINFO
*bmi
= (BITMAPINFO
*)(bfh
+ 1);
693 ret
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, len
);
694 if (!ret
|| !(p
= GlobalLock(ret
)))
708 /**************************************************************************
711 * Import enhanced metafile data, converting it to CF_ENHMETAFILE.
713 static HANDLE
import_enhmetafile(CFDataRef data
)
716 CFIndex len
= CFDataGetLength(data
);
718 TRACE("data %s\n", debugstr_cf(data
));
721 ret
= SetEnhMetaFileBits(len
, (const BYTE
*)CFDataGetBytePtr(data
));
727 /**************************************************************************
728 * import_enhmetafile_to_metafilepict
730 * Import enhanced metafile data, converting it to CF_METAFILEPICT.
732 static HANDLE
import_enhmetafile_to_metafilepict(CFDataRef data
)
738 if ((hmf
= GlobalAlloc(0, sizeof(*mfp
))) && (hemf
= import_enhmetafile(data
)))
740 ENHMETAHEADER header
;
741 HDC hdc
= CreateCompatibleDC(0);
742 unsigned int size
= GetWinMetaFileBits(hemf
, 0, NULL
, MM_ISOTROPIC
, hdc
);
745 bytes
= HeapAlloc(GetProcessHeap(), 0, size
);
746 if (bytes
&& GetEnhMetaFileHeader(hemf
, sizeof(header
), &header
) &&
747 GetWinMetaFileBits(hemf
, size
, bytes
, MM_ISOTROPIC
, hdc
))
749 mfp
= GlobalLock(hmf
);
750 mfp
->mm
= MM_ISOTROPIC
;
751 mfp
->xExt
= header
.rclFrame
.right
- header
.rclFrame
.left
;
752 mfp
->yExt
= header
.rclFrame
.bottom
- header
.rclFrame
.top
;
753 mfp
->hMF
= SetMetaFileBitsEx(size
, bytes
);
759 if (hdc
) DeleteDC(hdc
);
760 HeapFree(GetProcessHeap(), 0, bytes
);
761 DeleteEnhMetaFile(hemf
);
764 if (!ret
) GlobalFree(hmf
);
769 /**************************************************************************
770 * import_metafilepict
772 * Import metafile picture data, converting it to CF_METAFILEPICT.
774 static HANDLE
import_metafilepict(CFDataRef data
)
777 CFIndex len
= CFDataGetLength(data
);
780 TRACE("data %s\n", debugstr_cf(data
));
782 if (len
>= sizeof(*mfp
) && (ret
= GlobalAlloc(0, sizeof(*mfp
))))
784 const BYTE
*bytes
= (const BYTE
*)CFDataGetBytePtr(data
);
786 mfp
= GlobalLock(ret
);
787 memcpy(mfp
, bytes
, sizeof(*mfp
));
788 mfp
->hMF
= SetMetaFileBitsEx(len
- sizeof(*mfp
), bytes
+ sizeof(*mfp
));
796 /**************************************************************************
797 * import_metafilepict_to_enhmetafile
799 * Import metafile picture data, converting it to CF_ENHMETAFILE.
801 static HANDLE
import_metafilepict_to_enhmetafile(CFDataRef data
)
804 CFIndex len
= CFDataGetLength(data
);
805 const METAFILEPICT
*mfp
;
807 TRACE("data %s\n", debugstr_cf(data
));
809 if (len
>= sizeof(*mfp
))
811 mfp
= (const METAFILEPICT
*)CFDataGetBytePtr(data
);
812 ret
= SetWinMetaFileBits(len
- sizeof(*mfp
), (const BYTE
*)(mfp
+ 1), NULL
, mfp
);
819 /**************************************************************************
820 * import_nsfilenames_to_hdrop
822 * Import NSFilenamesPboardType data, converting the property-list-
823 * serialized array of path strings to CF_HDROP.
825 static HANDLE
import_nsfilenames_to_hdrop(CFDataRef data
)
832 WCHAR
**paths
= NULL
;
833 DROPFILES
* dropfiles
;
836 TRACE("data %s\n", debugstr_cf(data
));
838 names
= (CFArrayRef
)CFPropertyListCreateWithData(NULL
, data
, kCFPropertyListImmutable
,
840 if (!names
|| CFGetTypeID(names
) != CFArrayGetTypeID())
842 WARN("failed to interpret data as a CFArray\n");
846 count
= CFArrayGetCount(names
);
849 for (i
= 0; i
< count
; i
++)
852 CFStringRef name
= (CFStringRef
)CFArrayGetValueAtIndex(names
, i
);
853 TRACE(" %s\n", debugstr_cf(name
));
854 if (CFGetTypeID(name
) != CFStringGetTypeID())
856 WARN("non-string in array\n");
860 this_len
= CFStringGetMaximumSizeOfFileSystemRepresentation(name
);
865 buffer
= HeapAlloc(GetProcessHeap(), 0, len
);
868 WARN("failed to allocate buffer for file-system representations\n");
872 paths
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, count
* sizeof(paths
[0]));
875 WARN("failed to allocate array of DOS paths\n");
879 for (i
= 0; i
< count
; i
++)
881 CFStringRef name
= (CFStringRef
)CFArrayGetValueAtIndex(names
, i
);
882 if (!CFStringGetFileSystemRepresentation(name
, buffer
, len
))
884 WARN("failed to get file-system representation for %s\n", debugstr_cf(name
));
887 paths
[i
] = wine_get_dos_file_name(buffer
);
890 WARN("failed to get DOS path for %s\n", debugstr_a(buffer
));
895 len
= 1; /* for the terminating null */
896 for (i
= 0; i
< count
; i
++)
897 len
+= strlenW(paths
[i
]) + 1;
899 hdrop
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, sizeof(*dropfiles
) + len
* sizeof(WCHAR
));
900 if (!hdrop
|| !(dropfiles
= GlobalLock(hdrop
)))
902 WARN("failed to allocate HDROP\n");
908 dropfiles
->pFiles
= sizeof(*dropfiles
);
911 dropfiles
->fNC
= FALSE
;
912 dropfiles
->fWide
= TRUE
;
914 p
= (WCHAR
*)(dropfiles
+ 1);
915 for (i
= 0; i
< count
; i
++)
917 strcpyW(p
, paths
[i
]);
927 for (i
= 0; i
< count
; i
++)
928 HeapFree(GetProcessHeap(), 0, paths
[i
]);
929 HeapFree(GetProcessHeap(), 0, paths
);
931 HeapFree(GetProcessHeap(), 0, buffer
);
932 if (names
) CFRelease(names
);
937 /**************************************************************************
938 * import_oemtext_to_text
940 * Import CF_OEMTEXT data, converting the string to CF_TEXT.
942 static HANDLE
import_oemtext_to_text(CFDataRef data
)
944 return convert_text(CFDataGetBytePtr(data
), CFDataGetLength(data
), CP_OEMCP
, CP_ACP
);
948 /**************************************************************************
949 * import_oemtext_to_unicodetext
951 * Import CF_OEMTEXT data, converting the string to CF_UNICODETEXT.
953 static HANDLE
import_oemtext_to_unicodetext(CFDataRef data
)
955 return convert_text(CFDataGetBytePtr(data
), CFDataGetLength(data
), CP_OEMCP
, -1);
959 /**************************************************************************
960 * import_text_to_oemtext
962 * Import CF_TEXT data, converting the string to CF_OEMTEXT.
964 static HANDLE
import_text_to_oemtext(CFDataRef data
)
966 return convert_text(CFDataGetBytePtr(data
), CFDataGetLength(data
), CP_ACP
, CP_OEMCP
);
970 /**************************************************************************
971 * import_text_to_unicodetext
973 * Import CF_TEXT data, converting the string to CF_UNICODETEXT.
975 static HANDLE
import_text_to_unicodetext(CFDataRef data
)
977 return convert_text(CFDataGetBytePtr(data
), CFDataGetLength(data
), CP_ACP
, -1);
981 /**************************************************************************
982 * import_unicodetext_to_oemtext
984 * Import a CF_UNICODETEXT string, converting the string to CF_OEMTEXT.
986 static HANDLE
import_unicodetext_to_oemtext(CFDataRef data
)
988 return convert_text(CFDataGetBytePtr(data
), CFDataGetLength(data
), -1, CP_OEMCP
);
992 /**************************************************************************
993 * import_unicodetext_to_text
995 * Import a CF_UNICODETEXT string, converting the string to CF_TEXT.
997 static HANDLE
import_unicodetext_to_text(CFDataRef data
)
999 return convert_text(CFDataGetBytePtr(data
), CFDataGetLength(data
), -1, CP_ACP
);
1003 /**************************************************************************
1004 * import_utf8_to_oemtext
1006 * Import a UTF-8 string, converting the string to CF_OEMTEXT.
1008 static HANDLE
import_utf8_to_oemtext(CFDataRef data
)
1010 HANDLE unicode_handle
= import_utf8_to_unicodetext(data
);
1011 HANDLE ret
= convert_unicodetext_to_codepage(unicode_handle
, CP_OEMCP
);
1013 GlobalFree(unicode_handle
);
1018 /**************************************************************************
1019 * import_utf8_to_text
1021 * Import a UTF-8 string, converting the string to CF_TEXT.
1023 static HANDLE
import_utf8_to_text(CFDataRef data
)
1025 HANDLE unicode_handle
= import_utf8_to_unicodetext(data
);
1026 HANDLE ret
= convert_unicodetext_to_codepage(unicode_handle
, CP_ACP
);
1028 GlobalFree(unicode_handle
);
1033 /**************************************************************************
1034 * import_utf8_to_unicodetext
1036 * Import a UTF-8 string, converting the string to CF_UNICODETEXT.
1038 static HANDLE
import_utf8_to_unicodetext(CFDataRef data
)
1041 unsigned long src_len
;
1042 unsigned long new_lines
= 0;
1045 HANDLE unicode_handle
= NULL
;
1047 src
= CFDataGetBytePtr(data
);
1048 src_len
= CFDataGetLength(data
);
1049 for (i
= 0; i
< src_len
; i
++)
1055 if ((dst
= HeapAlloc(GetProcessHeap(), 0, src_len
+ new_lines
+ 1)))
1059 for (i
= 0, j
= 0; i
< src_len
; i
++)
1068 count
= MultiByteToWideChar(CP_UTF8
, 0, dst
, -1, NULL
, 0);
1069 unicode_handle
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, count
* sizeof(WCHAR
));
1073 WCHAR
*textW
= GlobalLock(unicode_handle
);
1074 MultiByteToWideChar(CP_UTF8
, 0, dst
, -1, textW
, count
);
1075 GlobalUnlock(unicode_handle
);
1078 HeapFree(GetProcessHeap(), 0, dst
);
1081 return unicode_handle
;
1085 /**************************************************************************
1086 * import_utf16_to_oemtext
1088 * Import a UTF-16 string, converting the string to CF_OEMTEXT.
1090 static HANDLE
import_utf16_to_oemtext(CFDataRef data
)
1092 HANDLE unicode_handle
= import_utf16_to_unicodetext(data
);
1093 HANDLE ret
= convert_unicodetext_to_codepage(unicode_handle
, CP_OEMCP
);
1095 GlobalFree(unicode_handle
);
1100 /**************************************************************************
1101 * import_utf16_to_text
1103 * Import a UTF-16 string, converting the string to CF_TEXT.
1105 static HANDLE
import_utf16_to_text(CFDataRef data
)
1107 HANDLE unicode_handle
= import_utf16_to_unicodetext(data
);
1108 HANDLE ret
= convert_unicodetext_to_codepage(unicode_handle
, CP_ACP
);
1110 GlobalFree(unicode_handle
);
1115 /**************************************************************************
1116 * import_utf16_to_unicodetext
1118 * Import a UTF-8 string, converting the string to CF_UNICODETEXT.
1120 static HANDLE
import_utf16_to_unicodetext(CFDataRef data
)
1123 unsigned long src_len
;
1124 unsigned long new_lines
= 0;
1127 HANDLE unicode_handle
;
1129 src
= (const WCHAR
*)CFDataGetBytePtr(data
);
1130 src_len
= CFDataGetLength(data
) / sizeof(WCHAR
);
1131 for (i
= 0; i
< src_len
; i
++)
1137 if ((unicode_handle
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, (src_len
+ new_lines
+ 1) * sizeof(WCHAR
))))
1139 dst
= GlobalLock(unicode_handle
);
1141 for (i
= 0, j
= 0; i
< src_len
; i
++)
1150 GlobalUnlock(unicode_handle
);
1153 return unicode_handle
;
1157 /**************************************************************************
1158 * export_clipboard_data
1160 * Generic export clipboard data routine.
1162 static CFDataRef
export_clipboard_data(HANDLE data
)
1168 len
= GlobalSize(data
);
1169 src
= GlobalLock(data
);
1170 if (!src
) return NULL
;
1172 ret
= CFDataCreate(NULL
, src
, len
);
1179 /**************************************************************************
1180 * export_bitmap_to_bmp
1182 * Export CF_BITMAP to BMP file format.
1184 static CFDataRef
export_bitmap_to_bmp(HANDLE data
)
1186 CFDataRef ret
= NULL
;
1189 dib
= create_dib_from_bitmap(data
);
1192 ret
= export_dib_to_bmp(dib
);
1200 /**************************************************************************
1201 * export_codepage_to_utf8
1203 * Export string data in a specified codepage to UTF-8.
1205 static CFDataRef
export_codepage_to_utf8(HANDLE data
, UINT cp
)
1207 CFDataRef ret
= NULL
;
1210 if ((str
= GlobalLock(data
)))
1212 HANDLE unicode
= convert_text(str
, GlobalSize(data
), cp
, -1);
1214 ret
= export_unicodetext_to_utf8(unicode
);
1216 GlobalFree(unicode
);
1224 /**************************************************************************
1225 * export_codepage_to_utf16
1227 * Export string data in a specified codepage to UTF-16.
1229 static CFDataRef
export_codepage_to_utf16(HANDLE data
, UINT cp
)
1231 CFDataRef ret
= NULL
;
1234 if ((str
= GlobalLock(data
)))
1236 HANDLE unicode
= convert_text(str
, GlobalSize(data
), cp
, -1);
1238 ret
= export_unicodetext_to_utf16(unicode
);
1240 GlobalFree(unicode
);
1248 /**************************************************************************
1251 * Export CF_DIB to BMP file format. This just entails prepending a BMP
1252 * file format header to the data.
1254 static CFDataRef
export_dib_to_bmp(HANDLE data
)
1256 CFMutableDataRef ret
= NULL
;
1259 BITMAPFILEHEADER bfh
;
1261 dibdata
= GlobalLock(data
);
1265 len
= sizeof(bfh
) + GlobalSize(data
);
1266 ret
= CFDataCreateMutable(NULL
, len
);
1269 bfh
.bfType
= 0x4d42; /* "BM" */
1271 bfh
.bfReserved1
= 0;
1272 bfh
.bfReserved2
= 0;
1273 bfh
.bfOffBits
= sizeof(bfh
) + bitmap_info_size((BITMAPINFO
*)dibdata
, DIB_RGB_COLORS
);
1274 CFDataAppendBytes(ret
, (UInt8
*)&bfh
, sizeof(bfh
));
1276 /* rest of bitmap is the same as the packed dib */
1277 CFDataAppendBytes(ret
, (UInt8
*)dibdata
, len
- sizeof(bfh
));
1286 /**************************************************************************
1287 * export_enhmetafile
1289 * Export an enhanced metafile to data.
1291 static CFDataRef
export_enhmetafile(HANDLE data
)
1293 CFMutableDataRef ret
= NULL
;
1294 unsigned int size
= GetEnhMetaFileBits(data
, 0, NULL
);
1296 TRACE("data %p\n", data
);
1298 ret
= CFDataCreateMutable(NULL
, size
);
1301 CFDataSetLength(ret
, size
);
1302 GetEnhMetaFileBits(data
, size
, (BYTE
*)CFDataGetMutableBytePtr(ret
));
1305 TRACE(" -> %s\n", debugstr_cf(ret
));
1310 /**************************************************************************
1311 * export_hdrop_to_filenames
1313 * Export CF_HDROP to NSFilenamesPboardType data, which is a CFArray of
1314 * CFStrings (holding Unix paths) which is serialized as a property list.
1316 static CFDataRef
export_hdrop_to_filenames(HANDLE data
)
1318 CFDataRef ret
= NULL
;
1319 DROPFILES
*dropfiles
;
1320 CFMutableArrayRef filenames
= NULL
;
1322 WCHAR
*buffer
= NULL
;
1323 size_t buffer_len
= 0;
1325 TRACE("data %p\n", data
);
1327 if (!(dropfiles
= GlobalLock(data
)))
1329 WARN("failed to lock data %p\n", data
);
1333 filenames
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1336 WARN("failed to create filenames array\n");
1340 p
= (char*)dropfiles
+ dropfiles
->pFiles
;
1341 while (dropfiles
->fWide
? *(WCHAR
*)p
: *(char*)p
)
1344 CFStringRef filename
;
1346 TRACE(" %s\n", dropfiles
->fWide
? debugstr_w(p
) : debugstr_a(p
));
1348 if (dropfiles
->fWide
)
1349 unixname
= wine_get_unix_file_name(p
);
1352 int len
= MultiByteToWideChar(CP_ACP
, 0, p
, -1, NULL
, 0);
1355 if (len
> buffer_len
)
1357 HeapFree(GetProcessHeap(), 0, buffer
);
1358 buffer_len
= len
* 2;
1359 buffer
= HeapAlloc(GetProcessHeap(), 0, buffer_len
* sizeof(*buffer
));
1362 MultiByteToWideChar(CP_ACP
, 0, p
, -1, buffer
, buffer_len
);
1363 unixname
= wine_get_unix_file_name(buffer
);
1370 WARN("failed to convert DOS path to Unix: %s\n",
1371 dropfiles
->fWide
? debugstr_w(p
) : debugstr_a(p
));
1375 if (dropfiles
->fWide
)
1376 p
= (WCHAR
*)p
+ strlenW(p
) + 1;
1378 p
= (char*)p
+ strlen(p
) + 1;
1380 filename
= CFStringCreateWithFileSystemRepresentation(NULL
, unixname
);
1381 HeapFree(GetProcessHeap(), 0, unixname
);
1384 WARN("failed to create CFString from Unix path %s\n", debugstr_a(unixname
));
1388 CFArrayAppendValue(filenames
, filename
);
1389 CFRelease(filename
);
1392 ret
= CFPropertyListCreateData(NULL
, filenames
, kCFPropertyListXMLFormat_v1_0
, 0, NULL
);
1395 HeapFree(GetProcessHeap(), 0, buffer
);
1397 if (filenames
) CFRelease(filenames
);
1398 TRACE(" -> %s\n", debugstr_cf(ret
));
1403 /**************************************************************************
1404 * export_metafilepict
1406 * Export a metafile to data.
1408 static CFDataRef
export_metafilepict(HANDLE data
)
1410 CFMutableDataRef ret
= NULL
;
1411 METAFILEPICT
*mfp
= GlobalLock(data
);
1412 unsigned int size
= GetMetaFileBitsEx(mfp
->hMF
, 0, NULL
);
1414 TRACE("data %p\n", data
);
1416 ret
= CFDataCreateMutable(NULL
, sizeof(*mfp
) + size
);
1419 CFDataAppendBytes(ret
, (UInt8
*)mfp
, sizeof(*mfp
));
1420 CFDataIncreaseLength(ret
, size
);
1421 GetMetaFileBitsEx(mfp
->hMF
, size
, (BYTE
*)CFDataGetMutableBytePtr(ret
) + sizeof(*mfp
));
1425 TRACE(" -> %s\n", debugstr_cf(ret
));
1430 /**************************************************************************
1431 * export_oemtext_to_utf8
1433 * Export CF_OEMTEXT to UTF-8.
1435 static CFDataRef
export_oemtext_to_utf8(HANDLE data
)
1437 return export_codepage_to_utf8(data
, CP_OEMCP
);
1441 /**************************************************************************
1442 * export_oemtext_to_utf16
1444 * Export CF_OEMTEXT to UTF-16.
1446 static CFDataRef
export_oemtext_to_utf16(HANDLE data
)
1448 return export_codepage_to_utf16(data
, CP_OEMCP
);
1452 /**************************************************************************
1453 * export_text_to_utf8
1455 * Export CF_TEXT to UTF-8.
1457 static CFDataRef
export_text_to_utf8(HANDLE data
)
1459 return export_codepage_to_utf8(data
, CP_ACP
);
1463 /**************************************************************************
1464 * export_text_to_utf16
1466 * Export CF_TEXT to UTF-16.
1468 static CFDataRef
export_text_to_utf16(HANDLE data
)
1470 return export_codepage_to_utf16(data
, CP_ACP
);
1474 /**************************************************************************
1475 * export_unicodetext_to_utf8
1477 * Export CF_UNICODETEXT to UTF-8.
1479 static CFDataRef
export_unicodetext_to_utf8(HANDLE data
)
1481 CFMutableDataRef ret
;
1485 src
= GlobalLock(data
);
1486 if (!src
) return NULL
;
1488 dst_len
= WideCharToMultiByte(CP_UTF8
, 0, src
, -1, NULL
, 0, NULL
, NULL
);
1489 if (dst_len
) dst_len
--; /* Leave off null terminator. */
1490 ret
= CFDataCreateMutable(NULL
, dst_len
);
1496 CFDataSetLength(ret
, dst_len
);
1497 dst
= (LPSTR
)CFDataGetMutableBytePtr(ret
);
1498 WideCharToMultiByte(CP_UTF8
, 0, src
, -1, dst
, dst_len
, NULL
, NULL
);
1500 /* Remove carriage returns */
1501 for (i
= 0, j
= 0; i
< dst_len
; i
++)
1503 if (dst
[i
] == '\r' &&
1504 (i
+ 1 >= dst_len
|| dst
[i
+ 1] == '\n' || dst
[i
+ 1] == '\0'))
1508 CFDataSetLength(ret
, j
);
1516 /**************************************************************************
1517 * export_unicodetext_to_utf16
1519 * Export CF_UNICODETEXT to UTF-16.
1521 static CFDataRef
export_unicodetext_to_utf16(HANDLE data
)
1523 CFMutableDataRef ret
;
1527 src
= GlobalLock(data
);
1528 if (!src
) return NULL
;
1530 src_len
= GlobalSize(data
) / sizeof(WCHAR
);
1531 if (src_len
) src_len
--; /* Leave off null terminator. */
1532 ret
= CFDataCreateMutable(NULL
, src_len
* sizeof(WCHAR
));
1538 CFDataSetLength(ret
, src_len
* sizeof(WCHAR
));
1539 dst
= (LPWSTR
)CFDataGetMutableBytePtr(ret
);
1541 /* Remove carriage returns */
1542 for (i
= 0, j
= 0; i
< src_len
; i
++)
1544 if (src
[i
] == '\r' &&
1545 (i
+ 1 >= src_len
|| src
[i
+ 1] == '\n' || src
[i
+ 1] == '\0'))
1549 CFDataSetLength(ret
, j
* sizeof(WCHAR
));
1557 /**************************************************************************
1558 * get_clipboard_info
1560 static BOOL
get_clipboard_info(LPCLIPBOARDINFO cbinfo
)
1564 SERVER_START_REQ(set_clipboard_info
)
1568 if (wine_server_call_err(req
))
1570 ERR("Failed to get clipboard owner.\n");
1574 cbinfo
->hwnd_owner
= wine_server_ptr_handle(reply
->old_owner
);
1575 cbinfo
->flags
= reply
->flags
;
1586 /**************************************************************************
1589 static BOOL
release_ownership(void)
1593 SERVER_START_REQ(set_clipboard_info
)
1595 req
->flags
= SET_CB_RELOWNER
| SET_CB_SEQNO
;
1597 if (wine_server_call_err(req
))
1598 ERR("Failed to set clipboard.\n");
1608 /**************************************************************************
1609 * macdrv_get_pasteboard_data
1611 HANDLE
macdrv_get_pasteboard_data(CFTypeRef pasteboard
, UINT desired_format
)
1616 CFStringRef type
, best_type
;
1617 WINE_CLIPFORMAT
* best_format
= NULL
;
1620 TRACE("pasteboard %p, desired_format %s\n", pasteboard
, debugstr_format(desired_format
));
1622 types
= macdrv_copy_pasteboard_types(pasteboard
);
1625 WARN("Failed to copy pasteboard types\n");
1629 count
= CFArrayGetCount(types
);
1630 TRACE("got %ld types\n", count
);
1632 for (i
= 0; (!best_format
|| best_format
->synthesized
) && i
< count
; i
++)
1634 WINE_CLIPFORMAT
* format
;
1636 type
= CFArrayGetValueAtIndex(types
, i
);
1639 while ((!best_format
|| best_format
->synthesized
) && (format
= format_for_type(format
, type
)))
1641 TRACE("for type %s got format %p/%s\n", debugstr_cf(type
), format
, debugstr_format(format
? format
->format_id
: 0));
1643 if (format
->format_id
== desired_format
)
1645 /* The best format is the matching one which is not synthesized. Failing that,
1646 the best format is the first matching synthesized format. */
1647 if (!format
->synthesized
|| !best_format
)
1650 best_format
= format
;
1658 CFDataRef pasteboard_data
= macdrv_copy_pasteboard_data(pasteboard
, best_type
);
1660 TRACE("got pasteboard data for type %s: %s\n", debugstr_cf(best_type
), debugstr_cf(pasteboard_data
));
1662 if (pasteboard_data
)
1664 data
= best_format
->import_func(pasteboard_data
);
1665 CFRelease(pasteboard_data
);
1670 TRACE(" -> %p\n", data
);
1675 /**************************************************************************
1676 * macdrv_pasteboard_has_format
1678 BOOL
macdrv_pasteboard_has_format(CFTypeRef pasteboard
, UINT desired_format
)
1685 TRACE("pasteboard %p, desired_format %s\n", pasteboard
, debugstr_format(desired_format
));
1687 types
= macdrv_copy_pasteboard_types(pasteboard
);
1690 WARN("Failed to copy pasteboard types\n");
1694 count
= CFArrayGetCount(types
);
1695 TRACE("got %d types\n", count
);
1697 for (i
= 0; !found
&& i
< count
; i
++)
1699 CFStringRef type
= CFArrayGetValueAtIndex(types
, i
);
1700 WINE_CLIPFORMAT
* format
;
1703 while (!found
&& (format
= format_for_type(format
, type
)))
1705 TRACE("for type %s got format %s\n", debugstr_cf(type
), debugstr_format(format
->format_id
));
1707 if (format
->format_id
== desired_format
)
1713 TRACE(" -> %d\n", found
);
1718 /**************************************************************************
1719 * macdrv_copy_pasteboard_formats
1721 CFArrayRef
macdrv_copy_pasteboard_formats(CFTypeRef pasteboard
)
1725 CFMutableArrayRef formats
;
1727 WINE_CLIPFORMAT
* format
;
1729 TRACE("pasteboard %p\n", pasteboard
);
1731 types
= macdrv_copy_pasteboard_types(pasteboard
);
1734 WARN("Failed to copy pasteboard types\n");
1738 count
= CFArrayGetCount(types
);
1739 TRACE("got %ld types\n", count
);
1747 formats
= CFArrayCreateMutable(NULL
, 0, NULL
);
1750 WARN("Failed to allocate formats array\n");
1755 for (i
= 0; i
< count
; i
++)
1757 CFStringRef type
= CFArrayGetValueAtIndex(types
, i
);
1761 while ((format
= format_for_type(format
, type
)))
1763 /* Suppose type is "public.utf8-plain-text". format->format_id will be each of
1764 CF_TEXT, CF_OEMTEXT, and CF_UNICODETEXT in turn. We want to look up the natural
1765 type for each of those IDs (e.g. CF_TEXT -> "org.winehq.builtin.text") and then see
1766 if that type is present in the pasteboard. If it is, then we don't want to add the
1767 format to the list yet because it would be out of order.
1769 For example, if a Mac app put "public.utf8-plain-text" and "public.tiff" on the
1770 pasteboard, then we want the Win32 clipboard formats to be CF_TEXT, CF_OEMTEXT, and
1771 CF_UNICODETEXT, and CF_TIFF, in that order. All of the text formats belong before
1772 CF_TIFF because the Mac app expressed that text was "better" than the TIFF. In
1773 this case, as soon as we encounter "public.utf8-plain-text" we should add all of
1774 the associated text format IDs.
1776 But if a Wine process put "org.winehq.builtin.unicodetext",
1777 "public.utf8-plain-text", "public.utf16-plain-text", and "public.tiff", then we
1778 want the clipboard formats to be CF_UNICODETEXT, CF_TIFF, CF_TEXT, and CF_OEMTEXT,
1779 in that order. The Windows program presumably added CF_UNICODETEXT and CF_TIFF.
1780 We're synthesizing CF_TEXT and CF_OEMTEXT from CF_UNICODETEXT but we want them to
1781 come after the non-synthesized CF_TIFF. In this case, we don't want to add the
1782 text formats upon encountering "public.utf8-plain-text",
1784 We tell the two cases apart by seeing that one of the natural types for the text
1785 formats (i.e. "org.winehq.builtin.unicodetext") is present on the pasteboard.
1786 "found" indicates that. */
1788 if (!format
->synthesized
)
1790 TRACE("for type %s got primary format %p/%s\n", debugstr_cf(type
), format
, debugstr_format(format
->format_id
));
1791 CFArrayAppendValue(formats
, (void*)format
->format_id
);
1794 else if (!found
&& format
->natural_format
&&
1795 CFArrayContainsValue(types
, CFRangeMake(0, count
), format
->natural_format
->type
))
1797 TRACE("for type %s deferring synthesized formats because type %s is also present\n",
1798 debugstr_cf(type
), debugstr_cf(format
->natural_format
->type
));
1805 while ((format
= format_for_type(format
, type
)))
1807 /* Don't override a real value with a synthesized value. */
1808 if (!CFArrayContainsValue(formats
, CFRangeMake(0, CFArrayGetCount(formats
)), (void*)format
->format_id
))
1810 TRACE("for type %s got synthesized format %p/%s\n", debugstr_cf(type
), format
, debugstr_format(format
->format_id
));
1811 CFArrayAppendValue(formats
, (void*)format
->format_id
);
1817 /* Now go back through the types adding the synthesized formats that we deferred before. */
1818 for (i
= 0; i
< count
; i
++)
1820 CFStringRef type
= CFArrayGetValueAtIndex(types
, i
);
1823 while ((format
= format_for_type(format
, type
)))
1825 if (format
->synthesized
)
1827 /* Don't override a real value with a synthesized value. */
1828 if (!CFArrayContainsValue(formats
, CFRangeMake(0, CFArrayGetCount(formats
)), (void*)format
->format_id
))
1830 TRACE("for type %s got synthesized format %p/%s\n", debugstr_cf(type
), format
, debugstr_format(format
->format_id
));
1831 CFArrayAppendValue(formats
, (void*)format
->format_id
);
1839 TRACE(" -> %s\n", debugstr_cf(formats
));
1844 /**************************************************************************
1845 * check_clipboard_ownership
1847 static void check_clipboard_ownership(HWND
*owner
)
1849 CLIPBOARDINFO cbinfo
;
1851 if (owner
) *owner
= NULL
;
1853 /* If Wine thinks we're the clipboard owner but Mac OS X thinks we're not
1854 the pasteboard owner, update Wine. */
1855 if (get_clipboard_info(&cbinfo
) && (cbinfo
.flags
& CB_PROCESS
))
1857 if (!(cbinfo
.flags
& CB_OPEN
) && !macdrv_is_pasteboard_owner())
1859 TRACE("Lost clipboard ownership\n");
1861 if (OpenClipboard(cbinfo
.hwnd_owner
))
1863 /* Destroy private objects */
1864 SendMessageW(cbinfo
.hwnd_owner
, WM_DESTROYCLIPBOARD
, 0, 0);
1866 /* Give up ownership of the windows clipboard */
1867 release_ownership();
1872 *owner
= cbinfo
.hwnd_owner
;
1877 /**************************************************************************
1878 * Mac User Driver Clipboard Exports
1879 **************************************************************************/
1882 /**************************************************************************
1883 * CountClipboardFormats (MACDRV.@)
1885 INT CDECL
macdrv_CountClipboardFormats(void)
1887 CFMutableSetRef seen_formats
;
1894 check_clipboard_ownership(NULL
);
1896 seen_formats
= CFSetCreateMutable(NULL
, 0, NULL
);
1899 WARN("Failed to allocate set to track seen formats\n");
1903 types
= macdrv_copy_pasteboard_types(NULL
);
1906 WARN("Failed to copy pasteboard types\n");
1907 CFRelease(seen_formats
);
1911 count
= CFArrayGetCount(types
);
1912 TRACE("got %ld types\n", count
);
1914 for (i
= 0; i
< count
; i
++)
1916 CFStringRef type
= CFArrayGetValueAtIndex(types
, i
);
1917 WINE_CLIPFORMAT
* format
;
1920 while ((format
= format_for_type(format
, type
)))
1922 TRACE("for type %s got format %p/%s\n", debugstr_cf(type
), format
, debugstr_format(format
->format_id
));
1924 if (!CFSetContainsValue(seen_formats
, (void*)format
->format_id
))
1927 CFSetAddValue(seen_formats
, (void*)format
->format_id
);
1933 CFRelease(seen_formats
);
1934 TRACE(" -> %d\n", ret
);
1939 /**************************************************************************
1940 * EmptyClipboard (MACDRV.@)
1942 * Empty cached clipboard data.
1944 void CDECL
macdrv_EmptyClipboard(void)
1947 check_clipboard_ownership(NULL
);
1948 macdrv_clear_pasteboard();
1952 /**************************************************************************
1953 * EndClipboardUpdate (MACDRV.@)
1955 void CDECL
macdrv_EndClipboardUpdate(void)
1958 check_clipboard_ownership(NULL
);
1962 /**************************************************************************
1963 * EnumClipboardFormats (MACDRV.@)
1965 UINT CDECL
macdrv_EnumClipboardFormats(UINT prev_format
)
1972 TRACE("prev_format %s\n", debugstr_format(prev_format
));
1973 check_clipboard_ownership(NULL
);
1975 formats
= macdrv_copy_pasteboard_formats(NULL
);
1978 count
= CFArrayGetCount(formats
);
1981 i
= CFArrayGetFirstIndexOfValue(formats
, CFRangeMake(0, count
), (void*)prev_format
);
1982 if (i
!= kCFNotFound
)
1988 if (i
!= kCFNotFound
&& i
< count
)
1989 ret
= (UINT
)CFArrayGetValueAtIndex(formats
, i
);
1994 TRACE(" -> %u\n", ret
);
1999 /**************************************************************************
2000 * GetClipboardData (MACDRV.@)
2002 HANDLE CDECL
macdrv_GetClipboardData(UINT desired_format
)
2004 check_clipboard_ownership(NULL
);
2006 return macdrv_get_pasteboard_data(NULL
, desired_format
);
2010 /**************************************************************************
2011 * IsClipboardFormatAvailable (MACDRV.@)
2013 BOOL CDECL
macdrv_IsClipboardFormatAvailable(UINT desired_format
)
2015 check_clipboard_ownership(NULL
);
2016 return macdrv_pasteboard_has_format(NULL
, desired_format
);
2020 /**************************************************************************
2021 * SetClipboardData (MACDRV.@)
2023 BOOL CDECL
macdrv_SetClipboardData(UINT format_id
, HANDLE data
, BOOL owner
)
2026 macdrv_window window
;
2027 WINE_CLIPFORMAT
*format
;
2028 CFDataRef cfdata
= NULL
;
2030 check_clipboard_ownership(&hwnd_owner
);
2031 window
= macdrv_get_cocoa_window(GetAncestor(hwnd_owner
, GA_ROOT
), FALSE
);
2032 TRACE("format_id %s data %p owner %d hwnd_owner %p window %p)\n", debugstr_format(format_id
), data
, owner
, hwnd_owner
, window
);
2034 format
= natural_format_for_format(format_id
);
2035 if (!format
&& !(format
= insert_clipboard_format(format_id
, NULL
)))
2037 WARN("Failed to register clipboard format %s\n", debugstr_format(format_id
));
2041 /* Export the data to the Mac pasteboard. */
2044 if (!format
->export_func
|| !(cfdata
= format
->export_func(data
)))
2046 WARN("Failed to export %s data to type %s\n", debugstr_format(format_id
), debugstr_cf(format
->type
));
2051 if (macdrv_set_pasteboard_data(format
->type
, cfdata
, window
))
2052 TRACE("Set pasteboard data for type %s: %s\n", debugstr_cf(format
->type
), debugstr_cf(cfdata
));
2055 WARN("Failed to set pasteboard data for type %s: %s\n", debugstr_cf(format
->type
), debugstr_cf(cfdata
));
2056 if (cfdata
) CFRelease(cfdata
);
2060 if (cfdata
) CFRelease(cfdata
);
2062 /* Find any other formats for this format_id (the exportable synthesized ones). */
2063 LIST_FOR_EACH_ENTRY(format
, &format_list
, WINE_CLIPFORMAT
, entry
)
2065 if (format
->format_id
== format_id
&& format
->synthesized
&& format
->export_func
)
2067 /* We have a synthesized format for this format ID. Add its type to the pasteboard. */
2068 TRACE("Synthesized from format %s: type %s\n", debugstr_format(format_id
), debugstr_cf(format
->type
));
2072 cfdata
= format
->export_func(data
);
2075 WARN("Failed to export %s data to type %s\n", debugstr_format(format
->format_id
), debugstr_cf(format
->type
));
2082 if (macdrv_set_pasteboard_data(format
->type
, cfdata
, window
))
2083 TRACE(" ... set pasteboard data: %s\n", debugstr_cf(cfdata
));
2085 WARN(" ... failed to set pasteboard data: %s\n", debugstr_cf(cfdata
));
2087 if (cfdata
) CFRelease(cfdata
);
2093 /* FIXME: According to MSDN, the caller is entitled to lock and read from
2094 data until CloseClipboard is called. So, we should defer this cleanup. */
2095 if ((format_id
>= CF_GDIOBJFIRST
&& format_id
<= CF_GDIOBJLAST
) ||
2096 format_id
== CF_BITMAP
||
2097 format_id
== CF_DIB
||
2098 format_id
== CF_PALETTE
)
2102 else if (format_id
== CF_METAFILEPICT
)
2104 DeleteMetaFile(((METAFILEPICT
*)GlobalLock(data
))->hMF
);
2107 else if (format_id
== CF_ENHMETAFILE
)
2109 DeleteEnhMetaFile(data
);
2111 else if (format_id
< CF_PRIVATEFIRST
|| CF_PRIVATELAST
< format_id
)
2121 /**************************************************************************
2122 * MACDRV Private Clipboard Exports
2123 **************************************************************************/
2126 /**************************************************************************
2127 * macdrv_clipboard_process_attach
2129 void macdrv_clipboard_process_attach(void)
2132 WINE_CLIPFORMAT
*format
;
2134 /* Register built-in formats */
2135 for (i
= 0; i
< sizeof(builtin_format_ids
)/sizeof(builtin_format_ids
[0]); i
++)
2137 if (!(format
= HeapAlloc(GetProcessHeap(), 0, sizeof(*format
)))) break;
2138 format
->format_id
= builtin_format_ids
[i
].id
;
2139 format
->type
= CFRetain(builtin_format_ids
[i
].type
);
2140 format
->import_func
= builtin_format_ids
[i
].import
;
2141 format
->export_func
= builtin_format_ids
[i
].export
;
2142 format
->synthesized
= builtin_format_ids
[i
].synthesized
;
2143 format
->natural_format
= NULL
;
2144 list_add_tail(&format_list
, &format
->entry
);
2147 LIST_FOR_EACH_ENTRY(format
, &format_list
, WINE_CLIPFORMAT
, entry
)
2149 if (format
->synthesized
)
2150 format
->natural_format
= natural_format_for_format(format
->format_id
);
2153 /* Register known mappings between Windows formats and Mac types */
2154 for (i
= 0; i
< sizeof(builtin_format_names
)/sizeof(builtin_format_names
[0]); i
++)
2156 if (!(format
= HeapAlloc(GetProcessHeap(), 0, sizeof(*format
)))) break;
2157 format
->format_id
= RegisterClipboardFormatW(builtin_format_names
[i
].name
);
2158 format
->type
= CFRetain(builtin_format_names
[i
].type
);
2159 format
->import_func
= builtin_format_names
[i
].import
;
2160 format
->export_func
= builtin_format_names
[i
].export
;
2161 format
->synthesized
= FALSE
;
2162 format
->natural_format
= NULL
;
2163 list_add_tail(&format_list
, &format
->entry
);
2168 /**************************************************************************
2169 * query_pasteboard_data
2171 BOOL
query_pasteboard_data(HWND hwnd
, CFStringRef type
)
2174 CLIPBOARDINFO cbinfo
;
2175 WINE_CLIPFORMAT
* format
;
2176 CFArrayRef types
= NULL
;
2179 TRACE("hwnd %p type %s\n", hwnd
, debugstr_cf(type
));
2181 if (get_clipboard_info(&cbinfo
))
2182 hwnd
= cbinfo
.hwnd_owner
;
2185 while ((format
= format_for_type(format
, type
)))
2187 TRACE("for type %s got format %p/%s\n", debugstr_cf(type
), format
, debugstr_format(format
->format_id
));
2189 if (!format
->synthesized
)
2191 TRACE("Sending WM_RENDERFORMAT message for format %s to hwnd %p\n", debugstr_format(format
->format_id
), hwnd
);
2192 SendMessageW(hwnd
, WM_RENDERFORMAT
, format
->format_id
, 0);
2199 types
= macdrv_copy_pasteboard_types(NULL
);
2202 WARN("Failed to copy pasteboard types\n");
2206 range
= CFRangeMake(0, CFArrayGetCount(types
));
2209 /* The type maps to a synthesized format. Now look up what type that format maps to natively
2210 (not synthesized). For example, if type is "public.utf8-plain-text", then this format may
2211 have an ID of CF_TEXT. From CF_TEXT, we want to find "org.winehq.builtin.text" to see if
2212 that type is present in the pasteboard. If it is, then the app must have promised it and
2213 we can ask it to render it. (If it had put it on the clipboard immediately, then the
2214 pasteboard would also have data for "public.utf8-plain-text" and we wouldn't be here.) If
2215 "org.winehq.builtin.text" is not on the pasteboard, then one of the other text formats is
2216 presumably responsible for the promise that we're trying to satisfy, so we keep looking. */
2217 if (format
->natural_format
&& CFArrayContainsValue(types
, range
, format
->natural_format
->type
))
2219 TRACE("Sending WM_RENDERFORMAT message for format %s to hwnd %p\n", debugstr_format(format
->format_id
), hwnd
);
2220 SendMessageW(hwnd
, WM_RENDERFORMAT
, format
->format_id
, 0);
2227 if (types
) CFRelease(types
);