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_dib_to_bitmap(CFDataRef data
);
77 static HANDLE
import_enhmetafile(CFDataRef data
);
78 static HANDLE
import_enhmetafile_to_metafilepict(CFDataRef data
);
79 static HANDLE
import_metafilepict(CFDataRef data
);
80 static HANDLE
import_metafilepict_to_enhmetafile(CFDataRef data
);
81 static HANDLE
import_nsfilenames_to_hdrop(CFDataRef data
);
82 static HANDLE
import_oemtext_to_text(CFDataRef data
);
83 static HANDLE
import_oemtext_to_unicodetext(CFDataRef data
);
84 static HANDLE
import_text_to_oemtext(CFDataRef data
);
85 static HANDLE
import_text_to_unicodetext(CFDataRef data
);
86 static HANDLE
import_unicodetext_to_oemtext(CFDataRef data
);
87 static HANDLE
import_unicodetext_to_text(CFDataRef data
);
88 static HANDLE
import_utf8_to_oemtext(CFDataRef data
);
89 static HANDLE
import_utf8_to_text(CFDataRef data
);
90 static HANDLE
import_utf8_to_unicodetext(CFDataRef data
);
91 static HANDLE
import_utf16_to_oemtext(CFDataRef data
);
92 static HANDLE
import_utf16_to_text(CFDataRef data
);
93 static HANDLE
import_utf16_to_unicodetext(CFDataRef data
);
95 static CFDataRef
export_clipboard_data(HANDLE data
);
96 static CFDataRef
export_bitmap_to_bmp(HANDLE data
);
97 static CFDataRef
export_bitmap_to_dib(HANDLE data
);
98 static CFDataRef
export_dib_to_bmp(HANDLE data
);
99 static CFDataRef
export_enhmetafile(HANDLE data
);
100 static CFDataRef
export_hdrop_to_filenames(HANDLE data
);
101 static CFDataRef
export_metafilepict(HANDLE data
);
102 static CFDataRef
export_oemtext_to_utf8(HANDLE data
);
103 static CFDataRef
export_oemtext_to_utf16(HANDLE data
);
104 static CFDataRef
export_text_to_utf8(HANDLE data
);
105 static CFDataRef
export_text_to_utf16(HANDLE data
);
106 static CFDataRef
export_unicodetext_to_utf8(HANDLE data
);
107 static CFDataRef
export_unicodetext_to_utf16(HANDLE data
);
110 /**************************************************************************
112 **************************************************************************/
114 /* Clipboard formats */
115 static struct list format_list
= LIST_INIT(format_list
);
117 /* There are two naming schemes involved and we want to have a mapping between
118 them. There are Win32 clipboard format names and there are Mac pasteboard
121 The Win32 standard clipboard formats don't have names, but they are associated
122 with Mac pasteboard types through the following tables, which are used to
123 initialize the format_list. Where possible, the standard clipboard formats
124 are mapped to predefined pasteboard type UTIs. Otherwise, we create Wine-
125 specific types of the form "org.winehq.builtin.<format>", where <format> is
126 the name of the symbolic constant for the format minus "CF_" and lowercased.
127 E.g. CF_BITMAP -> org.winehq.builtin.bitmap.
129 Win32 clipboard formats which originate in a Windows program may be registered
130 with an arbitrary name. We construct a Mac pasteboard type from these by
131 prepending "org.winehq.registered." to the registered name.
133 Likewise, Mac pasteboard types which originate in other apps may have
134 arbitrary type strings. We ignore these.
137 Win32 clipboard format names:
138 <none> standard clipboard format; maps via
139 format_list to either a predefined Mac UTI
140 or org.winehq.builtin.<format>.
141 <other> name registered within Win32 land; maps to
142 org.winehq.registered.<other>
143 Mac pasteboard type names:
144 org.winehq.builtin.<format ID> representation of Win32 standard clipboard
145 format for which there was no corresponding
146 predefined Mac UTI; maps via format_list
147 org.winehq.registered.<format name> representation of Win32 registered
148 clipboard format name; maps to <format name>
149 <other> Mac pasteboard type originating with system
150 or other apps; either maps via format_list
151 to a standard clipboard format or ignored
158 DRVIMPORTFUNC import
;
159 DRVEXPORTFUNC export
;
161 } builtin_format_ids
[] =
163 { CF_DIF
, CFSTR("org.winehq.builtin.dif"), import_clipboard_data
, export_clipboard_data
, FALSE
},
164 { CF_DSPBITMAP
, CFSTR("org.winehq.builtin.dspbitmap"), import_clipboard_data
, export_clipboard_data
, FALSE
},
165 { CF_DSPENHMETAFILE
, CFSTR("org.winehq.builtin.dspenhmetafile"), import_clipboard_data
, export_clipboard_data
, FALSE
},
166 { CF_DSPMETAFILEPICT
, CFSTR("org.winehq.builtin.dspmetafilepict"), import_clipboard_data
, export_clipboard_data
, FALSE
},
167 { CF_DSPTEXT
, CFSTR("org.winehq.builtin.dsptext"), import_clipboard_data
, export_clipboard_data
, FALSE
},
168 { CF_LOCALE
, CFSTR("org.winehq.builtin.locale"), import_clipboard_data
, export_clipboard_data
, FALSE
},
169 { CF_OWNERDISPLAY
, CFSTR("org.winehq.builtin.ownerdisplay"), import_clipboard_data
, export_clipboard_data
, FALSE
},
170 { CF_PALETTE
, CFSTR("org.winehq.builtin.palette"), import_clipboard_data
, export_clipboard_data
, FALSE
},
171 { CF_PENDATA
, CFSTR("org.winehq.builtin.pendata"), import_clipboard_data
, export_clipboard_data
, FALSE
},
172 { CF_RIFF
, CFSTR("org.winehq.builtin.riff"), import_clipboard_data
, export_clipboard_data
, FALSE
},
173 { CF_SYLK
, CFSTR("org.winehq.builtin.sylk"), import_clipboard_data
, export_clipboard_data
, FALSE
},
174 { CF_TIFF
, CFSTR("public.tiff"), import_clipboard_data
, export_clipboard_data
, FALSE
},
175 { CF_WAVE
, CFSTR("com.microsoft.waveform-audio"), import_clipboard_data
, export_clipboard_data
, FALSE
},
177 { CF_UNICODETEXT
, CFSTR("org.winehq.builtin.unicodetext"), import_clipboard_data
, export_clipboard_data
, FALSE
},
178 { CF_TEXT
, CFSTR("org.winehq.builtin.unicodetext"), import_unicodetext_to_text
, NULL
, TRUE
},
179 { CF_OEMTEXT
, CFSTR("org.winehq.builtin.unicodetext"), import_unicodetext_to_oemtext
, NULL
, TRUE
},
181 { CF_TEXT
, CFSTR("org.winehq.builtin.text"), import_clipboard_data
, export_clipboard_data
, FALSE
},
182 { CF_OEMTEXT
, CFSTR("org.winehq.builtin.text"), import_text_to_oemtext
, NULL
, TRUE
},
183 { CF_UNICODETEXT
, CFSTR("org.winehq.builtin.text"), import_text_to_unicodetext
, NULL
, TRUE
},
185 { CF_OEMTEXT
, CFSTR("org.winehq.builtin.oemtext"), import_clipboard_data
, export_clipboard_data
, FALSE
},
186 { CF_TEXT
, CFSTR("org.winehq.builtin.oemtext"), import_oemtext_to_text
, NULL
, TRUE
},
187 { CF_UNICODETEXT
, CFSTR("org.winehq.builtin.oemtext"), import_oemtext_to_unicodetext
, NULL
, TRUE
},
189 { CF_TEXT
, CFSTR("public.utf8-plain-text"), import_utf8_to_text
, export_text_to_utf8
, TRUE
},
190 { CF_OEMTEXT
, CFSTR("public.utf8-plain-text"), import_utf8_to_oemtext
, export_oemtext_to_utf8
, TRUE
},
191 { CF_UNICODETEXT
, CFSTR("public.utf8-plain-text"), import_utf8_to_unicodetext
, export_unicodetext_to_utf8
, TRUE
},
193 { CF_TEXT
, CFSTR("public.utf16-plain-text"), import_utf16_to_text
, export_text_to_utf16
, TRUE
},
194 { CF_OEMTEXT
, CFSTR("public.utf16-plain-text"), import_utf16_to_oemtext
, export_oemtext_to_utf16
, TRUE
},
195 { CF_UNICODETEXT
, CFSTR("public.utf16-plain-text"), import_utf16_to_unicodetext
, export_unicodetext_to_utf16
,TRUE
},
197 { CF_BITMAP
, CFSTR("org.winehq.builtin.bitmap"), import_bmp_to_bitmap
, export_bitmap_to_bmp
, FALSE
},
198 { CF_DIB
, CFSTR("org.winehq.builtin.bitmap"), import_bmp_to_dib
, export_dib_to_bmp
, TRUE
},
199 { CF_DIBV5
, CFSTR("org.winehq.builtin.bitmap"), import_bmp_to_dib
, export_dib_to_bmp
, TRUE
},
201 { CF_DIB
, CFSTR("org.winehq.builtin.dib"), import_clipboard_data
, export_clipboard_data
, FALSE
},
202 { CF_BITMAP
, CFSTR("org.winehq.builtin.dib"), import_dib_to_bitmap
, export_bitmap_to_dib
, TRUE
},
203 { CF_DIBV5
, CFSTR("org.winehq.builtin.dib"), import_clipboard_data
, export_clipboard_data
, TRUE
},
205 { CF_DIBV5
, CFSTR("org.winehq.builtin.dibv5"), import_clipboard_data
, export_clipboard_data
, FALSE
},
206 { CF_BITMAP
, CFSTR("org.winehq.builtin.dibv5"), import_dib_to_bitmap
, export_bitmap_to_dib
, TRUE
},
207 { CF_DIB
, CFSTR("org.winehq.builtin.dibv5"), import_clipboard_data
, export_clipboard_data
, TRUE
},
209 { CF_BITMAP
, CFSTR("com.microsoft.bmp"), import_bmp_to_bitmap
, export_bitmap_to_bmp
, TRUE
},
210 { CF_DIB
, CFSTR("com.microsoft.bmp"), import_bmp_to_dib
, export_dib_to_bmp
, TRUE
},
211 { CF_DIBV5
, CFSTR("com.microsoft.bmp"), import_bmp_to_dib
, export_dib_to_bmp
, TRUE
},
213 { CF_HDROP
, CFSTR("org.winehq.builtin.hdrop"), import_clipboard_data
, export_clipboard_data
, FALSE
},
214 { CF_HDROP
, CFSTR("NSFilenamesPboardType"), import_nsfilenames_to_hdrop
, export_hdrop_to_filenames
, TRUE
},
216 { CF_ENHMETAFILE
, CFSTR("org.winehq.builtin.enhmetafile"), import_enhmetafile
, export_enhmetafile
, FALSE
},
217 { CF_METAFILEPICT
, CFSTR("org.winehq.builtin.enhmetafile"), import_enhmetafile_to_metafilepict
, NULL
, TRUE
},
219 { CF_METAFILEPICT
, CFSTR("org.winehq.builtin.metafilepict"), import_metafilepict
, export_metafilepict
, FALSE
},
220 { CF_ENHMETAFILE
, CFSTR("org.winehq.builtin.metafilepict"), import_metafilepict_to_enhmetafile
, NULL
, TRUE
},
223 static const WCHAR wszRichTextFormat
[] = {'R','i','c','h',' ','T','e','x','t',' ','F','o','r','m','a','t',0};
224 static const WCHAR wszGIF
[] = {'G','I','F',0};
225 static const WCHAR wszJFIF
[] = {'J','F','I','F',0};
226 static const WCHAR wszPNG
[] = {'P','N','G',0};
227 static const WCHAR wszHTMLFormat
[] = {'H','T','M','L',' ','F','o','r','m','a','t',0};
232 DRVIMPORTFUNC import
;
233 DRVEXPORTFUNC export
;
234 } builtin_format_names
[] =
236 { wszRichTextFormat
, CFSTR("public.rtf"), import_clipboard_data
, export_clipboard_data
},
237 { wszGIF
, CFSTR("com.compuserve.gif"), import_clipboard_data
, export_clipboard_data
},
238 { wszJFIF
, CFSTR("public.jpeg"), import_clipboard_data
, export_clipboard_data
},
239 { wszPNG
, CFSTR("public.png"), import_clipboard_data
, export_clipboard_data
},
240 { wszHTMLFormat
, CFSTR("public.html"), import_clipboard_data
, export_clipboard_data
},
241 { CFSTR_SHELLURLW
, CFSTR("public.url"), import_utf8_to_text
, export_text_to_utf8
},
244 /* The prefix prepended to a Win32 clipboard format name to make a Mac pasteboard type. */
245 static const CFStringRef registered_name_type_prefix
= CFSTR("org.winehq.registered.");
248 /**************************************************************************
249 * Internal Clipboard implementation methods
250 **************************************************************************/
253 * format_list functions
256 /**************************************************************************
259 const char *debugstr_format(UINT id
)
263 if (GetClipboardFormatNameW(id
, buffer
, 256))
264 return wine_dbg_sprintf("0x%04x %s", id
, debugstr_w(buffer
));
268 #define BUILTIN(id) case id: return #id;
271 BUILTIN(CF_METAFILEPICT
)
281 BUILTIN(CF_UNICODETEXT
)
282 BUILTIN(CF_ENHMETAFILE
)
286 BUILTIN(CF_OWNERDISPLAY
)
288 BUILTIN(CF_DSPBITMAP
)
289 BUILTIN(CF_DSPMETAFILEPICT
)
290 BUILTIN(CF_DSPENHMETAFILE
)
292 default: return wine_dbg_sprintf("0x%04x", id
);
297 /**************************************************************************
298 * insert_clipboard_format
300 static WINE_CLIPFORMAT
*insert_clipboard_format(UINT id
, CFStringRef type
)
302 WINE_CLIPFORMAT
*format
;
304 format
= HeapAlloc(GetProcessHeap(), 0, sizeof(*format
));
308 WARN("No more memory for a new format!\n");
311 format
->format_id
= id
;
312 format
->import_func
= import_clipboard_data
;
313 format
->export_func
= export_clipboard_data
;
314 format
->synthesized
= FALSE
;
315 format
->natural_format
= NULL
;
318 format
->type
= CFStringCreateCopy(NULL
, type
);
323 if (!GetClipboardFormatNameW(format
->format_id
, buffer
, sizeof(buffer
) / sizeof(buffer
[0])))
325 WARN("failed to get name for format %s; error 0x%08x\n", debugstr_format(format
->format_id
), GetLastError());
326 HeapFree(GetProcessHeap(), 0, format
);
330 format
->type
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%@%S"),
331 registered_name_type_prefix
, buffer
);
334 list_add_tail(&format_list
, &format
->entry
);
336 TRACE("Registering format %s type %s\n", debugstr_format(format
->format_id
),
337 debugstr_cf(format
->type
));
343 /**************************************************************************
346 * Register a custom Mac clipboard format.
348 static WINE_CLIPFORMAT
* register_format(UINT id
, CFStringRef type
)
350 WINE_CLIPFORMAT
*format
;
352 /* walk format chain to see if it's already registered */
353 LIST_FOR_EACH_ENTRY(format
, &format_list
, WINE_CLIPFORMAT
, entry
)
354 if (format
->format_id
== id
) return format
;
356 return insert_clipboard_format(id
, type
);
360 /**************************************************************************
363 static WINE_CLIPFORMAT
* format_for_type(WINE_CLIPFORMAT
*current
, CFStringRef type
)
365 struct list
*ptr
= current
? ¤t
->entry
: &format_list
;
366 WINE_CLIPFORMAT
*format
= NULL
;
368 TRACE("current %p/%s type %s\n", current
, debugstr_format(current
? current
->format_id
: 0), debugstr_cf(type
));
370 while ((ptr
= list_next(&format_list
, ptr
)))
372 format
= LIST_ENTRY(ptr
, WINE_CLIPFORMAT
, entry
);
373 if (CFEqual(format
->type
, type
))
380 if (CFStringHasPrefix(type
, CFSTR("org.winehq.builtin.")))
382 ERR("Shouldn't happen. Built-in type %s should have matched something in format list.\n",
385 else if (CFStringHasPrefix(type
, registered_name_type_prefix
))
388 int len
= CFStringGetLength(type
) - CFStringGetLength(registered_name_type_prefix
);
390 name
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
));
391 CFStringGetCharacters(type
, CFRangeMake(CFStringGetLength(registered_name_type_prefix
), len
),
395 format
= register_format(RegisterClipboardFormatW(name
), type
);
397 ERR("Failed to register format for type %s name %s\n", debugstr_cf(type
), debugstr_w(name
));
399 HeapFree(GetProcessHeap(), 0, name
);
404 TRACE(" -> %p/%s\n", format
, debugstr_format(format
? format
->format_id
: 0));
409 /**************************************************************************
410 * natural_format_for_format
412 * Find the "natural" format for this format_id (the one which isn't
413 * synthesized from another type).
415 static WINE_CLIPFORMAT
* natural_format_for_format(UINT format_id
)
417 WINE_CLIPFORMAT
*format
;
419 LIST_FOR_EACH_ENTRY(format
, &format_list
, WINE_CLIPFORMAT
, entry
)
420 if (format
->format_id
== format_id
&& !format
->synthesized
) break;
422 if (&format
->entry
== &format_list
)
425 TRACE("%s -> %p/%s\n", debugstr_format(format_id
), format
, debugstr_cf(format
? format
->type
: NULL
));
430 /**************************************************************************
433 * Convert string data between code pages or to/from wide characters. The
434 * special value of (UINT)-1 for a code page indicates to use wide
437 static HANDLE
convert_text(const void *src
, int src_len
, UINT src_cp
, UINT dest_cp
)
445 if (src_cp
== (UINT
)-1)
448 wstr_len
= src_len
/ sizeof(WCHAR
);
454 wstr_len
= MultiByteToWideChar(src_cp
, 0, src
, src_len
, NULL
, 0);
455 if (!src_len
|| ((const char*)src
)[src_len
- 1]) wstr_len
+= 1;
456 temp
= HeapAlloc(GetProcessHeap(), 0, wstr_len
* sizeof(WCHAR
));
457 MultiByteToWideChar(src_cp
, 0, src
, src_len
, temp
, wstr_len
);
458 temp
[wstr_len
- 1] = 0;
462 if (dest_cp
== (UINT
)-1)
464 handle
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, wstr_len
* sizeof(WCHAR
));
465 if (handle
&& (p
= GlobalLock(handle
)))
467 memcpy(p
, wstr
, wstr_len
* sizeof(WCHAR
));
468 GlobalUnlock(handle
);
476 len
= WideCharToMultiByte(dest_cp
, 0, wstr
, wstr_len
, NULL
, 0, NULL
, NULL
);
477 if (!wstr_len
|| wstr
[wstr_len
- 1]) len
+= 1;
478 handle
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, len
);
480 if (handle
&& (p
= GlobalLock(handle
)))
482 WideCharToMultiByte(dest_cp
, 0, wstr
, wstr_len
, p
, len
, NULL
, NULL
);
484 GlobalUnlock(handle
);
493 /**************************************************************************
494 * convert_unicodetext_to_codepage
496 static HANDLE
convert_unicodetext_to_codepage(HANDLE unicode_handle
, UINT cp
)
498 LPWSTR unicode_string
= GlobalLock(unicode_handle
);
503 ret
= convert_text(unicode_string
, GlobalSize(unicode_handle
), -1, cp
);
504 GlobalUnlock(unicode_handle
);
511 /***********************************************************************
514 * Return the size of the bitmap info structure including color table.
516 static int bitmap_info_size(const BITMAPINFO
*info
, WORD coloruse
)
518 unsigned int colors
, size
, masks
= 0;
520 if (info
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
522 const BITMAPCOREHEADER
*core
= (const BITMAPCOREHEADER
*)info
;
523 colors
= (core
->bcBitCount
<= 8) ? 1 << core
->bcBitCount
: 0;
524 return sizeof(BITMAPCOREHEADER
) + colors
*
525 ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBTRIPLE
) : sizeof(WORD
));
527 else /* assume BITMAPINFOHEADER */
529 colors
= info
->bmiHeader
.biClrUsed
;
530 if (!colors
&& (info
->bmiHeader
.biBitCount
<= 8))
531 colors
= 1 << info
->bmiHeader
.biBitCount
;
532 if (info
->bmiHeader
.biCompression
== BI_BITFIELDS
) masks
= 3;
533 size
= max(info
->bmiHeader
.biSize
, sizeof(BITMAPINFOHEADER
) + masks
* sizeof(DWORD
));
534 return size
+ colors
* ((coloruse
== DIB_RGB_COLORS
) ? sizeof(RGBQUAD
) : sizeof(WORD
));
539 /***********************************************************************
540 * create_dib_from_bitmap
542 * Allocates a packed DIB and copies the bitmap data into it.
544 static HGLOBAL
create_dib_from_bitmap(HBITMAP hBmp
)
550 LPBITMAPINFOHEADER pbmiHeader
;
551 unsigned int cDataSize
, cPackedSize
, OffsetBits
;
554 if (!GetObjectW(hBmp
, sizeof(bmp
), &bmp
)) return 0;
557 * A packed DIB contains a BITMAPINFO structure followed immediately by
558 * an optional color palette and the pixel data.
561 /* Calculate the size of the packed DIB */
562 cDataSize
= abs(bmp
.bmHeight
) * (((bmp
.bmWidth
* bmp
.bmBitsPixel
+ 31) / 8) & ~3);
563 cPackedSize
= sizeof(BITMAPINFOHEADER
)
564 + ((bmp
.bmBitsPixel
<= 8) ? (sizeof(RGBQUAD
) * (1 << bmp
.bmBitsPixel
)) : 0)
566 /* Get the offset to the bits */
567 OffsetBits
= cPackedSize
- cDataSize
;
569 /* Allocate the packed DIB */
570 TRACE("\tAllocating packed DIB of size %d\n", cPackedSize
);
571 hPackedDIB
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, cPackedSize
);
574 WARN("Could not allocate packed DIB!\n");
578 /* A packed DIB starts with a BITMAPINFOHEADER */
579 pPackedDIB
= GlobalLock(hPackedDIB
);
580 pbmiHeader
= (LPBITMAPINFOHEADER
)pPackedDIB
;
582 /* Init the BITMAPINFOHEADER */
583 pbmiHeader
->biSize
= sizeof(BITMAPINFOHEADER
);
584 pbmiHeader
->biWidth
= bmp
.bmWidth
;
585 pbmiHeader
->biHeight
= bmp
.bmHeight
;
586 pbmiHeader
->biPlanes
= 1;
587 pbmiHeader
->biBitCount
= bmp
.bmBitsPixel
;
588 pbmiHeader
->biCompression
= BI_RGB
;
589 pbmiHeader
->biSizeImage
= 0;
590 pbmiHeader
->biXPelsPerMeter
= pbmiHeader
->biYPelsPerMeter
= 0;
591 pbmiHeader
->biClrUsed
= 0;
592 pbmiHeader
->biClrImportant
= 0;
594 /* Retrieve the DIB bits from the bitmap and fill in the
595 * DIB color table if present */
597 nLinesCopied
= GetDIBits(hdc
, /* Handle to device context */
598 hBmp
, /* Handle to bitmap */
599 0, /* First scan line to set in dest bitmap */
600 bmp
.bmHeight
, /* Number of scan lines to copy */
601 pPackedDIB
+ OffsetBits
, /* [out] Address of array for bitmap bits */
602 (LPBITMAPINFO
) pbmiHeader
, /* [out] Address of BITMAPINFO structure */
603 0); /* RGB or palette index */
604 GlobalUnlock(hPackedDIB
);
607 /* Cleanup if GetDIBits failed */
608 if (nLinesCopied
!= bmp
.bmHeight
)
610 TRACE("\tGetDIBits returned %d. Actual lines=%d\n", nLinesCopied
, bmp
.bmHeight
);
611 GlobalFree(hPackedDIB
);
618 /**************************************************************************
619 * create_bitmap_from_dib
621 * Given a packed DIB, creates a bitmap object from it.
623 static HANDLE
create_bitmap_from_dib(HANDLE dib
)
628 if (dib
&& (bmi
= GlobalLock(dib
)))
635 offset
= bitmap_info_size(bmi
, DIB_RGB_COLORS
);
637 ret
= CreateDIBitmap(hdc
, &bmi
->bmiHeader
, CBM_INIT
, (LPBYTE
)bmi
+ offset
,
638 bmi
, DIB_RGB_COLORS
);
641 ReleaseDC(NULL
, hdc
);
648 /**************************************************************************
649 * import_clipboard_data
651 * Generic import clipboard data routine.
653 static HANDLE
import_clipboard_data(CFDataRef data
)
655 HANDLE data_handle
= NULL
;
657 size_t len
= CFDataGetLength(data
);
662 /* Turn on the DDESHARE flag to enable shared 32 bit memory */
663 data_handle
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, len
);
667 if ((p
= GlobalLock(data_handle
)))
669 memcpy(p
, CFDataGetBytePtr(data
), len
);
670 GlobalUnlock(data_handle
);
674 GlobalFree(data_handle
);
683 /**************************************************************************
684 * import_bmp_to_bitmap
686 * Import BMP data, converting to CF_BITMAP format.
688 static HANDLE
import_bmp_to_bitmap(CFDataRef data
)
691 HANDLE dib
= import_bmp_to_dib(data
);
693 ret
= create_bitmap_from_dib(dib
);
700 /**************************************************************************
703 * Import BMP data, converting to CF_DIB or CF_DIBV5 format. This just
704 * entails stripping the BMP file format header.
706 static HANDLE
import_bmp_to_dib(CFDataRef data
)
709 BITMAPFILEHEADER
*bfh
= (BITMAPFILEHEADER
*)CFDataGetBytePtr(data
);
710 CFIndex len
= CFDataGetLength(data
);
712 if (len
>= sizeof(*bfh
) + sizeof(BITMAPCOREHEADER
) &&
713 bfh
->bfType
== 0x4d42 /* "BM" */)
715 BITMAPINFO
*bmi
= (BITMAPINFO
*)(bfh
+ 1);
719 ret
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, len
);
720 if (!ret
|| !(p
= GlobalLock(ret
)))
734 /**************************************************************************
735 * import_dib_to_bitmap
737 * Import device-independent bitmap data, converting to CF_BITMAP format.
739 static HANDLE
import_dib_to_bitmap(CFDataRef data
)
742 HANDLE dib
= import_clipboard_data(data
);
744 ret
= create_bitmap_from_dib(dib
);
752 /**************************************************************************
755 * Import enhanced metafile data, converting it to CF_ENHMETAFILE.
757 static HANDLE
import_enhmetafile(CFDataRef data
)
760 CFIndex len
= CFDataGetLength(data
);
762 TRACE("data %s\n", debugstr_cf(data
));
765 ret
= SetEnhMetaFileBits(len
, (const BYTE
*)CFDataGetBytePtr(data
));
771 /**************************************************************************
772 * import_enhmetafile_to_metafilepict
774 * Import enhanced metafile data, converting it to CF_METAFILEPICT.
776 static HANDLE
import_enhmetafile_to_metafilepict(CFDataRef data
)
782 if ((hmf
= GlobalAlloc(0, sizeof(*mfp
))) && (hemf
= import_enhmetafile(data
)))
784 ENHMETAHEADER header
;
785 HDC hdc
= CreateCompatibleDC(0);
786 unsigned int size
= GetWinMetaFileBits(hemf
, 0, NULL
, MM_ISOTROPIC
, hdc
);
789 bytes
= HeapAlloc(GetProcessHeap(), 0, size
);
790 if (bytes
&& GetEnhMetaFileHeader(hemf
, sizeof(header
), &header
) &&
791 GetWinMetaFileBits(hemf
, size
, bytes
, MM_ISOTROPIC
, hdc
))
793 mfp
= GlobalLock(hmf
);
794 mfp
->mm
= MM_ISOTROPIC
;
795 mfp
->xExt
= header
.rclFrame
.right
- header
.rclFrame
.left
;
796 mfp
->yExt
= header
.rclFrame
.bottom
- header
.rclFrame
.top
;
797 mfp
->hMF
= SetMetaFileBitsEx(size
, bytes
);
803 if (hdc
) DeleteDC(hdc
);
804 HeapFree(GetProcessHeap(), 0, bytes
);
805 DeleteEnhMetaFile(hemf
);
808 if (!ret
) GlobalFree(hmf
);
813 /**************************************************************************
814 * import_metafilepict
816 * Import metafile picture data, converting it to CF_METAFILEPICT.
818 static HANDLE
import_metafilepict(CFDataRef data
)
821 CFIndex len
= CFDataGetLength(data
);
824 TRACE("data %s\n", debugstr_cf(data
));
826 if (len
>= sizeof(*mfp
) && (ret
= GlobalAlloc(0, sizeof(*mfp
))))
828 const BYTE
*bytes
= (const BYTE
*)CFDataGetBytePtr(data
);
830 mfp
= GlobalLock(ret
);
831 memcpy(mfp
, bytes
, sizeof(*mfp
));
832 mfp
->hMF
= SetMetaFileBitsEx(len
- sizeof(*mfp
), bytes
+ sizeof(*mfp
));
840 /**************************************************************************
841 * import_metafilepict_to_enhmetafile
843 * Import metafile picture data, converting it to CF_ENHMETAFILE.
845 static HANDLE
import_metafilepict_to_enhmetafile(CFDataRef data
)
848 CFIndex len
= CFDataGetLength(data
);
849 const METAFILEPICT
*mfp
;
851 TRACE("data %s\n", debugstr_cf(data
));
853 if (len
>= sizeof(*mfp
))
855 mfp
= (const METAFILEPICT
*)CFDataGetBytePtr(data
);
856 ret
= SetWinMetaFileBits(len
- sizeof(*mfp
), (const BYTE
*)(mfp
+ 1), NULL
, mfp
);
863 /**************************************************************************
864 * import_nsfilenames_to_hdrop
866 * Import NSFilenamesPboardType data, converting the property-list-
867 * serialized array of path strings to CF_HDROP.
869 static HANDLE
import_nsfilenames_to_hdrop(CFDataRef data
)
876 WCHAR
**paths
= NULL
;
877 DROPFILES
* dropfiles
;
880 TRACE("data %s\n", debugstr_cf(data
));
882 names
= (CFArrayRef
)CFPropertyListCreateWithData(NULL
, data
, kCFPropertyListImmutable
,
884 if (!names
|| CFGetTypeID(names
) != CFArrayGetTypeID())
886 WARN("failed to interpret data as a CFArray\n");
890 count
= CFArrayGetCount(names
);
893 for (i
= 0; i
< count
; i
++)
896 CFStringRef name
= (CFStringRef
)CFArrayGetValueAtIndex(names
, i
);
897 TRACE(" %s\n", debugstr_cf(name
));
898 if (CFGetTypeID(name
) != CFStringGetTypeID())
900 WARN("non-string in array\n");
904 this_len
= CFStringGetMaximumSizeOfFileSystemRepresentation(name
);
909 buffer
= HeapAlloc(GetProcessHeap(), 0, len
);
912 WARN("failed to allocate buffer for file-system representations\n");
916 paths
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, count
* sizeof(paths
[0]));
919 WARN("failed to allocate array of DOS paths\n");
923 for (i
= 0; i
< count
; i
++)
925 CFStringRef name
= (CFStringRef
)CFArrayGetValueAtIndex(names
, i
);
926 if (!CFStringGetFileSystemRepresentation(name
, buffer
, len
))
928 WARN("failed to get file-system representation for %s\n", debugstr_cf(name
));
931 paths
[i
] = wine_get_dos_file_name(buffer
);
934 WARN("failed to get DOS path for %s\n", debugstr_a(buffer
));
939 len
= 1; /* for the terminating null */
940 for (i
= 0; i
< count
; i
++)
941 len
+= strlenW(paths
[i
]) + 1;
943 hdrop
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, sizeof(*dropfiles
) + len
* sizeof(WCHAR
));
944 if (!hdrop
|| !(dropfiles
= GlobalLock(hdrop
)))
946 WARN("failed to allocate HDROP\n");
952 dropfiles
->pFiles
= sizeof(*dropfiles
);
955 dropfiles
->fNC
= FALSE
;
956 dropfiles
->fWide
= TRUE
;
958 p
= (WCHAR
*)(dropfiles
+ 1);
959 for (i
= 0; i
< count
; i
++)
961 strcpyW(p
, paths
[i
]);
971 for (i
= 0; i
< count
; i
++)
972 HeapFree(GetProcessHeap(), 0, paths
[i
]);
973 HeapFree(GetProcessHeap(), 0, paths
);
975 HeapFree(GetProcessHeap(), 0, buffer
);
976 if (names
) CFRelease(names
);
981 /**************************************************************************
982 * import_oemtext_to_text
984 * Import CF_OEMTEXT data, converting the string to CF_TEXT.
986 static HANDLE
import_oemtext_to_text(CFDataRef data
)
988 return convert_text(CFDataGetBytePtr(data
), CFDataGetLength(data
), CP_OEMCP
, CP_ACP
);
992 /**************************************************************************
993 * import_oemtext_to_unicodetext
995 * Import CF_OEMTEXT data, converting the string to CF_UNICODETEXT.
997 static HANDLE
import_oemtext_to_unicodetext(CFDataRef data
)
999 return convert_text(CFDataGetBytePtr(data
), CFDataGetLength(data
), CP_OEMCP
, -1);
1003 /**************************************************************************
1004 * import_text_to_oemtext
1006 * Import CF_TEXT data, converting the string to CF_OEMTEXT.
1008 static HANDLE
import_text_to_oemtext(CFDataRef data
)
1010 return convert_text(CFDataGetBytePtr(data
), CFDataGetLength(data
), CP_ACP
, CP_OEMCP
);
1014 /**************************************************************************
1015 * import_text_to_unicodetext
1017 * Import CF_TEXT data, converting the string to CF_UNICODETEXT.
1019 static HANDLE
import_text_to_unicodetext(CFDataRef data
)
1021 return convert_text(CFDataGetBytePtr(data
), CFDataGetLength(data
), CP_ACP
, -1);
1025 /**************************************************************************
1026 * import_unicodetext_to_oemtext
1028 * Import a CF_UNICODETEXT string, converting the string to CF_OEMTEXT.
1030 static HANDLE
import_unicodetext_to_oemtext(CFDataRef data
)
1032 return convert_text(CFDataGetBytePtr(data
), CFDataGetLength(data
), -1, CP_OEMCP
);
1036 /**************************************************************************
1037 * import_unicodetext_to_text
1039 * Import a CF_UNICODETEXT string, converting the string to CF_TEXT.
1041 static HANDLE
import_unicodetext_to_text(CFDataRef data
)
1043 return convert_text(CFDataGetBytePtr(data
), CFDataGetLength(data
), -1, CP_ACP
);
1047 /**************************************************************************
1048 * import_utf8_to_oemtext
1050 * Import a UTF-8 string, converting the string to CF_OEMTEXT.
1052 static HANDLE
import_utf8_to_oemtext(CFDataRef data
)
1054 HANDLE unicode_handle
= import_utf8_to_unicodetext(data
);
1055 HANDLE ret
= convert_unicodetext_to_codepage(unicode_handle
, CP_OEMCP
);
1057 GlobalFree(unicode_handle
);
1062 /**************************************************************************
1063 * import_utf8_to_text
1065 * Import a UTF-8 string, converting the string to CF_TEXT.
1067 static HANDLE
import_utf8_to_text(CFDataRef data
)
1069 HANDLE unicode_handle
= import_utf8_to_unicodetext(data
);
1070 HANDLE ret
= convert_unicodetext_to_codepage(unicode_handle
, CP_ACP
);
1072 GlobalFree(unicode_handle
);
1077 /**************************************************************************
1078 * import_utf8_to_unicodetext
1080 * Import a UTF-8 string, converting the string to CF_UNICODETEXT.
1082 static HANDLE
import_utf8_to_unicodetext(CFDataRef data
)
1085 unsigned long src_len
;
1086 unsigned long new_lines
= 0;
1089 HANDLE unicode_handle
= NULL
;
1091 src
= CFDataGetBytePtr(data
);
1092 src_len
= CFDataGetLength(data
);
1093 for (i
= 0; i
< src_len
; i
++)
1099 if ((dst
= HeapAlloc(GetProcessHeap(), 0, src_len
+ new_lines
+ 1)))
1103 for (i
= 0, j
= 0; i
< src_len
; i
++)
1112 count
= MultiByteToWideChar(CP_UTF8
, 0, dst
, -1, NULL
, 0);
1113 unicode_handle
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, count
* sizeof(WCHAR
));
1117 WCHAR
*textW
= GlobalLock(unicode_handle
);
1118 MultiByteToWideChar(CP_UTF8
, 0, dst
, -1, textW
, count
);
1119 GlobalUnlock(unicode_handle
);
1122 HeapFree(GetProcessHeap(), 0, dst
);
1125 return unicode_handle
;
1129 /**************************************************************************
1130 * import_utf16_to_oemtext
1132 * Import a UTF-16 string, converting the string to CF_OEMTEXT.
1134 static HANDLE
import_utf16_to_oemtext(CFDataRef data
)
1136 HANDLE unicode_handle
= import_utf16_to_unicodetext(data
);
1137 HANDLE ret
= convert_unicodetext_to_codepage(unicode_handle
, CP_OEMCP
);
1139 GlobalFree(unicode_handle
);
1144 /**************************************************************************
1145 * import_utf16_to_text
1147 * Import a UTF-16 string, converting the string to CF_TEXT.
1149 static HANDLE
import_utf16_to_text(CFDataRef data
)
1151 HANDLE unicode_handle
= import_utf16_to_unicodetext(data
);
1152 HANDLE ret
= convert_unicodetext_to_codepage(unicode_handle
, CP_ACP
);
1154 GlobalFree(unicode_handle
);
1159 /**************************************************************************
1160 * import_utf16_to_unicodetext
1162 * Import a UTF-8 string, converting the string to CF_UNICODETEXT.
1164 static HANDLE
import_utf16_to_unicodetext(CFDataRef data
)
1167 unsigned long src_len
;
1168 unsigned long new_lines
= 0;
1171 HANDLE unicode_handle
;
1173 src
= (const WCHAR
*)CFDataGetBytePtr(data
);
1174 src_len
= CFDataGetLength(data
) / sizeof(WCHAR
);
1175 for (i
= 0; i
< src_len
; i
++)
1181 if ((unicode_handle
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_DDESHARE
, (src_len
+ new_lines
+ 1) * sizeof(WCHAR
))))
1183 dst
= GlobalLock(unicode_handle
);
1185 for (i
= 0, j
= 0; i
< src_len
; i
++)
1194 GlobalUnlock(unicode_handle
);
1197 return unicode_handle
;
1201 /**************************************************************************
1202 * export_clipboard_data
1204 * Generic export clipboard data routine.
1206 static CFDataRef
export_clipboard_data(HANDLE data
)
1212 len
= GlobalSize(data
);
1213 src
= GlobalLock(data
);
1214 if (!src
) return NULL
;
1216 ret
= CFDataCreate(NULL
, src
, len
);
1223 /**************************************************************************
1224 * export_bitmap_to_bmp
1226 * Export CF_BITMAP to BMP file format.
1228 static CFDataRef
export_bitmap_to_bmp(HANDLE data
)
1230 CFDataRef ret
= NULL
;
1233 dib
= create_dib_from_bitmap(data
);
1236 ret
= export_dib_to_bmp(dib
);
1244 /**************************************************************************
1245 * export_bitmap_to_dib
1247 * Export CF_BITMAP to a raw packed device-independent bitmap.
1249 static CFDataRef
export_bitmap_to_dib(HANDLE data
)
1251 CFDataRef ret
= NULL
;
1254 dib
= create_dib_from_bitmap(data
);
1257 ret
= export_clipboard_data(dib
);
1265 /**************************************************************************
1266 * export_codepage_to_utf8
1268 * Export string data in a specified codepage to UTF-8.
1270 static CFDataRef
export_codepage_to_utf8(HANDLE data
, UINT cp
)
1272 CFDataRef ret
= NULL
;
1275 if ((str
= GlobalLock(data
)))
1277 HANDLE unicode
= convert_text(str
, GlobalSize(data
), cp
, -1);
1279 ret
= export_unicodetext_to_utf8(unicode
);
1281 GlobalFree(unicode
);
1289 /**************************************************************************
1290 * export_codepage_to_utf16
1292 * Export string data in a specified codepage to UTF-16.
1294 static CFDataRef
export_codepage_to_utf16(HANDLE data
, UINT cp
)
1296 CFDataRef ret
= NULL
;
1299 if ((str
= GlobalLock(data
)))
1301 HANDLE unicode
= convert_text(str
, GlobalSize(data
), cp
, -1);
1303 ret
= export_unicodetext_to_utf16(unicode
);
1305 GlobalFree(unicode
);
1313 /**************************************************************************
1316 * Export CF_DIB or CF_DIBV5 to BMP file format. This just entails
1317 * prepending a BMP file format header to the data.
1319 static CFDataRef
export_dib_to_bmp(HANDLE data
)
1321 CFMutableDataRef ret
= NULL
;
1324 BITMAPFILEHEADER bfh
;
1326 dibdata
= GlobalLock(data
);
1330 len
= sizeof(bfh
) + GlobalSize(data
);
1331 ret
= CFDataCreateMutable(NULL
, len
);
1334 bfh
.bfType
= 0x4d42; /* "BM" */
1336 bfh
.bfReserved1
= 0;
1337 bfh
.bfReserved2
= 0;
1338 bfh
.bfOffBits
= sizeof(bfh
) + bitmap_info_size((BITMAPINFO
*)dibdata
, DIB_RGB_COLORS
);
1339 CFDataAppendBytes(ret
, (UInt8
*)&bfh
, sizeof(bfh
));
1341 /* rest of bitmap is the same as the packed dib */
1342 CFDataAppendBytes(ret
, (UInt8
*)dibdata
, len
- sizeof(bfh
));
1351 /**************************************************************************
1352 * export_enhmetafile
1354 * Export an enhanced metafile to data.
1356 static CFDataRef
export_enhmetafile(HANDLE data
)
1358 CFMutableDataRef ret
= NULL
;
1359 unsigned int size
= GetEnhMetaFileBits(data
, 0, NULL
);
1361 TRACE("data %p\n", data
);
1363 ret
= CFDataCreateMutable(NULL
, size
);
1366 CFDataSetLength(ret
, size
);
1367 GetEnhMetaFileBits(data
, size
, (BYTE
*)CFDataGetMutableBytePtr(ret
));
1370 TRACE(" -> %s\n", debugstr_cf(ret
));
1375 /**************************************************************************
1376 * export_hdrop_to_filenames
1378 * Export CF_HDROP to NSFilenamesPboardType data, which is a CFArray of
1379 * CFStrings (holding Unix paths) which is serialized as a property list.
1381 static CFDataRef
export_hdrop_to_filenames(HANDLE data
)
1383 CFDataRef ret
= NULL
;
1384 DROPFILES
*dropfiles
;
1385 CFMutableArrayRef filenames
= NULL
;
1387 WCHAR
*buffer
= NULL
;
1388 size_t buffer_len
= 0;
1390 TRACE("data %p\n", data
);
1392 if (!(dropfiles
= GlobalLock(data
)))
1394 WARN("failed to lock data %p\n", data
);
1398 filenames
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1401 WARN("failed to create filenames array\n");
1405 p
= (char*)dropfiles
+ dropfiles
->pFiles
;
1406 while (dropfiles
->fWide
? *(WCHAR
*)p
: *(char*)p
)
1409 CFStringRef filename
;
1411 TRACE(" %s\n", dropfiles
->fWide
? debugstr_w(p
) : debugstr_a(p
));
1413 if (dropfiles
->fWide
)
1414 unixname
= wine_get_unix_file_name(p
);
1417 int len
= MultiByteToWideChar(CP_ACP
, 0, p
, -1, NULL
, 0);
1420 if (len
> buffer_len
)
1422 HeapFree(GetProcessHeap(), 0, buffer
);
1423 buffer_len
= len
* 2;
1424 buffer
= HeapAlloc(GetProcessHeap(), 0, buffer_len
* sizeof(*buffer
));
1427 MultiByteToWideChar(CP_ACP
, 0, p
, -1, buffer
, buffer_len
);
1428 unixname
= wine_get_unix_file_name(buffer
);
1435 WARN("failed to convert DOS path to Unix: %s\n",
1436 dropfiles
->fWide
? debugstr_w(p
) : debugstr_a(p
));
1440 if (dropfiles
->fWide
)
1441 p
= (WCHAR
*)p
+ strlenW(p
) + 1;
1443 p
= (char*)p
+ strlen(p
) + 1;
1445 filename
= CFStringCreateWithFileSystemRepresentation(NULL
, unixname
);
1446 HeapFree(GetProcessHeap(), 0, unixname
);
1449 WARN("failed to create CFString from Unix path %s\n", debugstr_a(unixname
));
1453 CFArrayAppendValue(filenames
, filename
);
1454 CFRelease(filename
);
1457 ret
= CFPropertyListCreateData(NULL
, filenames
, kCFPropertyListXMLFormat_v1_0
, 0, NULL
);
1460 HeapFree(GetProcessHeap(), 0, buffer
);
1462 if (filenames
) CFRelease(filenames
);
1463 TRACE(" -> %s\n", debugstr_cf(ret
));
1468 /**************************************************************************
1469 * export_metafilepict
1471 * Export a metafile to data.
1473 static CFDataRef
export_metafilepict(HANDLE data
)
1475 CFMutableDataRef ret
= NULL
;
1476 METAFILEPICT
*mfp
= GlobalLock(data
);
1477 unsigned int size
= GetMetaFileBitsEx(mfp
->hMF
, 0, NULL
);
1479 TRACE("data %p\n", data
);
1481 ret
= CFDataCreateMutable(NULL
, sizeof(*mfp
) + size
);
1484 CFDataAppendBytes(ret
, (UInt8
*)mfp
, sizeof(*mfp
));
1485 CFDataIncreaseLength(ret
, size
);
1486 GetMetaFileBitsEx(mfp
->hMF
, size
, (BYTE
*)CFDataGetMutableBytePtr(ret
) + sizeof(*mfp
));
1490 TRACE(" -> %s\n", debugstr_cf(ret
));
1495 /**************************************************************************
1496 * export_oemtext_to_utf8
1498 * Export CF_OEMTEXT to UTF-8.
1500 static CFDataRef
export_oemtext_to_utf8(HANDLE data
)
1502 return export_codepage_to_utf8(data
, CP_OEMCP
);
1506 /**************************************************************************
1507 * export_oemtext_to_utf16
1509 * Export CF_OEMTEXT to UTF-16.
1511 static CFDataRef
export_oemtext_to_utf16(HANDLE data
)
1513 return export_codepage_to_utf16(data
, CP_OEMCP
);
1517 /**************************************************************************
1518 * export_text_to_utf8
1520 * Export CF_TEXT to UTF-8.
1522 static CFDataRef
export_text_to_utf8(HANDLE data
)
1524 return export_codepage_to_utf8(data
, CP_ACP
);
1528 /**************************************************************************
1529 * export_text_to_utf16
1531 * Export CF_TEXT to UTF-16.
1533 static CFDataRef
export_text_to_utf16(HANDLE data
)
1535 return export_codepage_to_utf16(data
, CP_ACP
);
1539 /**************************************************************************
1540 * export_unicodetext_to_utf8
1542 * Export CF_UNICODETEXT to UTF-8.
1544 static CFDataRef
export_unicodetext_to_utf8(HANDLE data
)
1546 CFMutableDataRef ret
;
1550 src
= GlobalLock(data
);
1551 if (!src
) return NULL
;
1553 dst_len
= WideCharToMultiByte(CP_UTF8
, 0, src
, -1, NULL
, 0, NULL
, NULL
);
1554 if (dst_len
) dst_len
--; /* Leave off null terminator. */
1555 ret
= CFDataCreateMutable(NULL
, dst_len
);
1561 CFDataSetLength(ret
, dst_len
);
1562 dst
= (LPSTR
)CFDataGetMutableBytePtr(ret
);
1563 WideCharToMultiByte(CP_UTF8
, 0, src
, -1, dst
, dst_len
, NULL
, NULL
);
1565 /* Remove carriage returns */
1566 for (i
= 0, j
= 0; i
< dst_len
; i
++)
1568 if (dst
[i
] == '\r' &&
1569 (i
+ 1 >= dst_len
|| dst
[i
+ 1] == '\n' || dst
[i
+ 1] == '\0'))
1573 CFDataSetLength(ret
, j
);
1581 /**************************************************************************
1582 * export_unicodetext_to_utf16
1584 * Export CF_UNICODETEXT to UTF-16.
1586 static CFDataRef
export_unicodetext_to_utf16(HANDLE data
)
1588 CFMutableDataRef ret
;
1592 src
= GlobalLock(data
);
1593 if (!src
) return NULL
;
1595 src_len
= GlobalSize(data
) / sizeof(WCHAR
);
1596 if (src_len
) src_len
--; /* Leave off null terminator. */
1597 ret
= CFDataCreateMutable(NULL
, src_len
* sizeof(WCHAR
));
1603 CFDataSetLength(ret
, src_len
* sizeof(WCHAR
));
1604 dst
= (LPWSTR
)CFDataGetMutableBytePtr(ret
);
1606 /* Remove carriage returns */
1607 for (i
= 0, j
= 0; i
< src_len
; i
++)
1609 if (src
[i
] == '\r' &&
1610 (i
+ 1 >= src_len
|| src
[i
+ 1] == '\n' || src
[i
+ 1] == '\0'))
1614 CFDataSetLength(ret
, j
* sizeof(WCHAR
));
1622 /**************************************************************************
1623 * get_clipboard_info
1625 static BOOL
get_clipboard_info(LPCLIPBOARDINFO cbinfo
)
1629 SERVER_START_REQ(set_clipboard_info
)
1633 if (wine_server_call_err(req
))
1635 ERR("Failed to get clipboard owner.\n");
1639 cbinfo
->hwnd_owner
= wine_server_ptr_handle(reply
->old_owner
);
1640 cbinfo
->flags
= reply
->flags
;
1651 /**************************************************************************
1654 static BOOL
release_ownership(void)
1658 SERVER_START_REQ(set_clipboard_info
)
1660 req
->flags
= SET_CB_RELOWNER
| SET_CB_SEQNO
;
1662 if (wine_server_call_err(req
))
1663 ERR("Failed to set clipboard.\n");
1673 /**************************************************************************
1674 * macdrv_get_pasteboard_data
1676 HANDLE
macdrv_get_pasteboard_data(CFTypeRef pasteboard
, UINT desired_format
)
1681 CFStringRef type
, best_type
;
1682 WINE_CLIPFORMAT
* best_format
= NULL
;
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 %ld types\n", count
);
1697 for (i
= 0; (!best_format
|| best_format
->synthesized
) && i
< count
; i
++)
1699 WINE_CLIPFORMAT
* format
;
1701 type
= CFArrayGetValueAtIndex(types
, i
);
1704 while ((!best_format
|| best_format
->synthesized
) && (format
= format_for_type(format
, type
)))
1706 TRACE("for type %s got format %p/%s\n", debugstr_cf(type
), format
, debugstr_format(format
? format
->format_id
: 0));
1708 if (format
->format_id
== desired_format
)
1710 /* The best format is the matching one which is not synthesized. Failing that,
1711 the best format is the first matching synthesized format. */
1712 if (!format
->synthesized
|| !best_format
)
1715 best_format
= format
;
1723 CFDataRef pasteboard_data
= macdrv_copy_pasteboard_data(pasteboard
, best_type
);
1725 TRACE("got pasteboard data for type %s: %s\n", debugstr_cf(best_type
), debugstr_cf(pasteboard_data
));
1727 if (pasteboard_data
)
1729 data
= best_format
->import_func(pasteboard_data
);
1730 CFRelease(pasteboard_data
);
1735 TRACE(" -> %p\n", data
);
1740 /**************************************************************************
1741 * macdrv_pasteboard_has_format
1743 BOOL
macdrv_pasteboard_has_format(CFTypeRef pasteboard
, UINT desired_format
)
1750 TRACE("pasteboard %p, desired_format %s\n", pasteboard
, debugstr_format(desired_format
));
1752 types
= macdrv_copy_pasteboard_types(pasteboard
);
1755 WARN("Failed to copy pasteboard types\n");
1759 count
= CFArrayGetCount(types
);
1760 TRACE("got %d types\n", count
);
1762 for (i
= 0; !found
&& i
< count
; i
++)
1764 CFStringRef type
= CFArrayGetValueAtIndex(types
, i
);
1765 WINE_CLIPFORMAT
* format
;
1768 while (!found
&& (format
= format_for_type(format
, type
)))
1770 TRACE("for type %s got format %s\n", debugstr_cf(type
), debugstr_format(format
->format_id
));
1772 if (format
->format_id
== desired_format
)
1778 TRACE(" -> %d\n", found
);
1783 /**************************************************************************
1784 * macdrv_copy_pasteboard_formats
1786 CFArrayRef
macdrv_copy_pasteboard_formats(CFTypeRef pasteboard
)
1790 CFMutableArrayRef formats
;
1792 WINE_CLIPFORMAT
* format
;
1794 TRACE("pasteboard %p\n", pasteboard
);
1796 types
= macdrv_copy_pasteboard_types(pasteboard
);
1799 WARN("Failed to copy pasteboard types\n");
1803 count
= CFArrayGetCount(types
);
1804 TRACE("got %ld types\n", count
);
1812 formats
= CFArrayCreateMutable(NULL
, 0, NULL
);
1815 WARN("Failed to allocate formats array\n");
1820 for (i
= 0; i
< count
; i
++)
1822 CFStringRef type
= CFArrayGetValueAtIndex(types
, i
);
1826 while ((format
= format_for_type(format
, type
)))
1828 /* Suppose type is "public.utf8-plain-text". format->format_id will be each of
1829 CF_TEXT, CF_OEMTEXT, and CF_UNICODETEXT in turn. We want to look up the natural
1830 type for each of those IDs (e.g. CF_TEXT -> "org.winehq.builtin.text") and then see
1831 if that type is present in the pasteboard. If it is, then we don't want to add the
1832 format to the list yet because it would be out of order.
1834 For example, if a Mac app put "public.utf8-plain-text" and "public.tiff" on the
1835 pasteboard, then we want the Win32 clipboard formats to be CF_TEXT, CF_OEMTEXT, and
1836 CF_UNICODETEXT, and CF_TIFF, in that order. All of the text formats belong before
1837 CF_TIFF because the Mac app expressed that text was "better" than the TIFF. In
1838 this case, as soon as we encounter "public.utf8-plain-text" we should add all of
1839 the associated text format IDs.
1841 But if a Wine process put "org.winehq.builtin.unicodetext",
1842 "public.utf8-plain-text", "public.utf16-plain-text", and "public.tiff", then we
1843 want the clipboard formats to be CF_UNICODETEXT, CF_TIFF, CF_TEXT, and CF_OEMTEXT,
1844 in that order. The Windows program presumably added CF_UNICODETEXT and CF_TIFF.
1845 We're synthesizing CF_TEXT and CF_OEMTEXT from CF_UNICODETEXT but we want them to
1846 come after the non-synthesized CF_TIFF. In this case, we don't want to add the
1847 text formats upon encountering "public.utf8-plain-text",
1849 We tell the two cases apart by seeing that one of the natural types for the text
1850 formats (i.e. "org.winehq.builtin.unicodetext") is present on the pasteboard.
1851 "found" indicates that. */
1853 if (!format
->synthesized
)
1855 TRACE("for type %s got primary format %p/%s\n", debugstr_cf(type
), format
, debugstr_format(format
->format_id
));
1856 CFArrayAppendValue(formats
, (void*)format
->format_id
);
1859 else if (!found
&& format
->natural_format
&&
1860 CFArrayContainsValue(types
, CFRangeMake(0, count
), format
->natural_format
->type
))
1862 TRACE("for type %s deferring synthesized formats because type %s is also present\n",
1863 debugstr_cf(type
), debugstr_cf(format
->natural_format
->type
));
1870 while ((format
= format_for_type(format
, type
)))
1872 /* Don't override a real value with a synthesized value. */
1873 if (!CFArrayContainsValue(formats
, CFRangeMake(0, CFArrayGetCount(formats
)), (void*)format
->format_id
))
1875 TRACE("for type %s got synthesized format %p/%s\n", debugstr_cf(type
), format
, debugstr_format(format
->format_id
));
1876 CFArrayAppendValue(formats
, (void*)format
->format_id
);
1882 /* Now go back through the types adding the synthesized formats that we deferred before. */
1883 for (i
= 0; i
< count
; i
++)
1885 CFStringRef type
= CFArrayGetValueAtIndex(types
, i
);
1888 while ((format
= format_for_type(format
, type
)))
1890 if (format
->synthesized
)
1892 /* Don't override a real value with a synthesized value. */
1893 if (!CFArrayContainsValue(formats
, CFRangeMake(0, CFArrayGetCount(formats
)), (void*)format
->format_id
))
1895 TRACE("for type %s got synthesized format %p/%s\n", debugstr_cf(type
), format
, debugstr_format(format
->format_id
));
1896 CFArrayAppendValue(formats
, (void*)format
->format_id
);
1904 TRACE(" -> %s\n", debugstr_cf(formats
));
1909 /**************************************************************************
1910 * check_clipboard_ownership
1912 static void check_clipboard_ownership(HWND
*owner
)
1914 CLIPBOARDINFO cbinfo
;
1916 if (owner
) *owner
= NULL
;
1918 /* If Wine thinks we're the clipboard owner but Mac OS X thinks we're not
1919 the pasteboard owner, update Wine. */
1920 if (get_clipboard_info(&cbinfo
) && (cbinfo
.flags
& CB_PROCESS
))
1922 if (!(cbinfo
.flags
& CB_OPEN
) && !macdrv_is_pasteboard_owner())
1924 TRACE("Lost clipboard ownership\n");
1926 if (OpenClipboard(cbinfo
.hwnd_owner
))
1928 /* Destroy private objects */
1929 SendMessageW(cbinfo
.hwnd_owner
, WM_DESTROYCLIPBOARD
, 0, 0);
1931 /* Give up ownership of the windows clipboard */
1932 release_ownership();
1937 *owner
= cbinfo
.hwnd_owner
;
1942 /**************************************************************************
1943 * Mac User Driver Clipboard Exports
1944 **************************************************************************/
1947 /**************************************************************************
1948 * CountClipboardFormats (MACDRV.@)
1950 INT CDECL
macdrv_CountClipboardFormats(void)
1952 CFMutableSetRef seen_formats
;
1959 check_clipboard_ownership(NULL
);
1961 seen_formats
= CFSetCreateMutable(NULL
, 0, NULL
);
1964 WARN("Failed to allocate set to track seen formats\n");
1968 types
= macdrv_copy_pasteboard_types(NULL
);
1971 WARN("Failed to copy pasteboard types\n");
1972 CFRelease(seen_formats
);
1976 count
= CFArrayGetCount(types
);
1977 TRACE("got %ld types\n", count
);
1979 for (i
= 0; i
< count
; i
++)
1981 CFStringRef type
= CFArrayGetValueAtIndex(types
, i
);
1982 WINE_CLIPFORMAT
* format
;
1985 while ((format
= format_for_type(format
, type
)))
1987 TRACE("for type %s got format %p/%s\n", debugstr_cf(type
), format
, debugstr_format(format
->format_id
));
1989 if (!CFSetContainsValue(seen_formats
, (void*)format
->format_id
))
1992 CFSetAddValue(seen_formats
, (void*)format
->format_id
);
1998 CFRelease(seen_formats
);
1999 TRACE(" -> %d\n", ret
);
2004 /**************************************************************************
2005 * EmptyClipboard (MACDRV.@)
2007 * Empty cached clipboard data.
2009 void CDECL
macdrv_EmptyClipboard(void)
2012 check_clipboard_ownership(NULL
);
2013 macdrv_clear_pasteboard();
2017 /**************************************************************************
2018 * EndClipboardUpdate (MACDRV.@)
2020 void CDECL
macdrv_EndClipboardUpdate(void)
2023 check_clipboard_ownership(NULL
);
2027 /**************************************************************************
2028 * EnumClipboardFormats (MACDRV.@)
2030 UINT CDECL
macdrv_EnumClipboardFormats(UINT prev_format
)
2037 TRACE("prev_format %s\n", debugstr_format(prev_format
));
2038 check_clipboard_ownership(NULL
);
2040 formats
= macdrv_copy_pasteboard_formats(NULL
);
2043 count
= CFArrayGetCount(formats
);
2046 i
= CFArrayGetFirstIndexOfValue(formats
, CFRangeMake(0, count
), (void*)prev_format
);
2047 if (i
!= kCFNotFound
)
2053 if (i
!= kCFNotFound
&& i
< count
)
2054 ret
= (UINT
)CFArrayGetValueAtIndex(formats
, i
);
2059 TRACE(" -> %u\n", ret
);
2064 /**************************************************************************
2065 * GetClipboardData (MACDRV.@)
2067 HANDLE CDECL
macdrv_GetClipboardData(UINT desired_format
)
2069 check_clipboard_ownership(NULL
);
2071 return macdrv_get_pasteboard_data(NULL
, desired_format
);
2075 /**************************************************************************
2076 * IsClipboardFormatAvailable (MACDRV.@)
2078 BOOL CDECL
macdrv_IsClipboardFormatAvailable(UINT desired_format
)
2080 check_clipboard_ownership(NULL
);
2081 return macdrv_pasteboard_has_format(NULL
, desired_format
);
2085 /**************************************************************************
2086 * SetClipboardData (MACDRV.@)
2088 BOOL CDECL
macdrv_SetClipboardData(UINT format_id
, HANDLE data
, BOOL owner
)
2091 macdrv_window window
;
2092 WINE_CLIPFORMAT
*format
;
2093 CFDataRef cfdata
= NULL
;
2095 check_clipboard_ownership(&hwnd_owner
);
2096 window
= macdrv_get_cocoa_window(GetAncestor(hwnd_owner
, GA_ROOT
), FALSE
);
2097 TRACE("format_id %s data %p owner %d hwnd_owner %p window %p)\n", debugstr_format(format_id
), data
, owner
, hwnd_owner
, window
);
2099 format
= natural_format_for_format(format_id
);
2100 if (!format
&& !(format
= insert_clipboard_format(format_id
, NULL
)))
2102 WARN("Failed to register clipboard format %s\n", debugstr_format(format_id
));
2106 /* Export the data to the Mac pasteboard. */
2109 if (!format
->export_func
|| !(cfdata
= format
->export_func(data
)))
2111 WARN("Failed to export %s data to type %s\n", debugstr_format(format_id
), debugstr_cf(format
->type
));
2116 if (macdrv_set_pasteboard_data(format
->type
, cfdata
, window
))
2117 TRACE("Set pasteboard data for type %s: %s\n", debugstr_cf(format
->type
), debugstr_cf(cfdata
));
2120 WARN("Failed to set pasteboard data for type %s: %s\n", debugstr_cf(format
->type
), debugstr_cf(cfdata
));
2121 if (cfdata
) CFRelease(cfdata
);
2125 if (cfdata
) CFRelease(cfdata
);
2127 /* Find any other formats for this format_id (the exportable synthesized ones). */
2128 LIST_FOR_EACH_ENTRY(format
, &format_list
, WINE_CLIPFORMAT
, entry
)
2130 if (format
->format_id
== format_id
&& format
->synthesized
&& format
->export_func
)
2132 /* We have a synthesized format for this format ID. Add its type to the pasteboard. */
2133 TRACE("Synthesized from format %s: type %s\n", debugstr_format(format_id
), debugstr_cf(format
->type
));
2137 cfdata
= format
->export_func(data
);
2140 WARN("Failed to export %s data to type %s\n", debugstr_format(format
->format_id
), debugstr_cf(format
->type
));
2147 if (macdrv_set_pasteboard_data(format
->type
, cfdata
, window
))
2148 TRACE(" ... set pasteboard data: %s\n", debugstr_cf(cfdata
));
2150 WARN(" ... failed to set pasteboard data: %s\n", debugstr_cf(cfdata
));
2152 if (cfdata
) CFRelease(cfdata
);
2158 /* FIXME: According to MSDN, the caller is entitled to lock and read from
2159 data until CloseClipboard is called. So, we should defer this cleanup. */
2160 if ((format_id
>= CF_GDIOBJFIRST
&& format_id
<= CF_GDIOBJLAST
) ||
2161 format_id
== CF_BITMAP
||
2162 format_id
== CF_DIB
||
2163 format_id
== CF_PALETTE
)
2167 else if (format_id
== CF_METAFILEPICT
)
2169 DeleteMetaFile(((METAFILEPICT
*)GlobalLock(data
))->hMF
);
2172 else if (format_id
== CF_ENHMETAFILE
)
2174 DeleteEnhMetaFile(data
);
2176 else if (format_id
< CF_PRIVATEFIRST
|| CF_PRIVATELAST
< format_id
)
2186 /**************************************************************************
2187 * MACDRV Private Clipboard Exports
2188 **************************************************************************/
2191 /**************************************************************************
2192 * macdrv_clipboard_process_attach
2194 void macdrv_clipboard_process_attach(void)
2197 WINE_CLIPFORMAT
*format
;
2199 /* Register built-in formats */
2200 for (i
= 0; i
< sizeof(builtin_format_ids
)/sizeof(builtin_format_ids
[0]); i
++)
2202 if (!(format
= HeapAlloc(GetProcessHeap(), 0, sizeof(*format
)))) break;
2203 format
->format_id
= builtin_format_ids
[i
].id
;
2204 format
->type
= CFRetain(builtin_format_ids
[i
].type
);
2205 format
->import_func
= builtin_format_ids
[i
].import
;
2206 format
->export_func
= builtin_format_ids
[i
].export
;
2207 format
->synthesized
= builtin_format_ids
[i
].synthesized
;
2208 format
->natural_format
= NULL
;
2209 list_add_tail(&format_list
, &format
->entry
);
2212 LIST_FOR_EACH_ENTRY(format
, &format_list
, WINE_CLIPFORMAT
, entry
)
2214 if (format
->synthesized
)
2215 format
->natural_format
= natural_format_for_format(format
->format_id
);
2218 /* Register known mappings between Windows formats and Mac types */
2219 for (i
= 0; i
< sizeof(builtin_format_names
)/sizeof(builtin_format_names
[0]); i
++)
2221 if (!(format
= HeapAlloc(GetProcessHeap(), 0, sizeof(*format
)))) break;
2222 format
->format_id
= RegisterClipboardFormatW(builtin_format_names
[i
].name
);
2223 format
->type
= CFRetain(builtin_format_names
[i
].type
);
2224 format
->import_func
= builtin_format_names
[i
].import
;
2225 format
->export_func
= builtin_format_names
[i
].export
;
2226 format
->synthesized
= FALSE
;
2227 format
->natural_format
= NULL
;
2228 list_add_tail(&format_list
, &format
->entry
);
2233 /**************************************************************************
2234 * query_pasteboard_data
2236 BOOL
query_pasteboard_data(HWND hwnd
, CFStringRef type
)
2239 CLIPBOARDINFO cbinfo
;
2240 WINE_CLIPFORMAT
* format
;
2241 CFArrayRef types
= NULL
;
2244 TRACE("hwnd %p type %s\n", hwnd
, debugstr_cf(type
));
2246 if (get_clipboard_info(&cbinfo
))
2247 hwnd
= cbinfo
.hwnd_owner
;
2250 while ((format
= format_for_type(format
, type
)))
2252 TRACE("for type %s got format %p/%s\n", debugstr_cf(type
), format
, debugstr_format(format
->format_id
));
2254 if (!format
->synthesized
)
2256 TRACE("Sending WM_RENDERFORMAT message for format %s to hwnd %p\n", debugstr_format(format
->format_id
), hwnd
);
2257 SendMessageW(hwnd
, WM_RENDERFORMAT
, format
->format_id
, 0);
2264 types
= macdrv_copy_pasteboard_types(NULL
);
2267 WARN("Failed to copy pasteboard types\n");
2271 range
= CFRangeMake(0, CFArrayGetCount(types
));
2274 /* The type maps to a synthesized format. Now look up what type that format maps to natively
2275 (not synthesized). For example, if type is "public.utf8-plain-text", then this format may
2276 have an ID of CF_TEXT. From CF_TEXT, we want to find "org.winehq.builtin.text" to see if
2277 that type is present in the pasteboard. If it is, then the app must have promised it and
2278 we can ask it to render it. (If it had put it on the clipboard immediately, then the
2279 pasteboard would also have data for "public.utf8-plain-text" and we wouldn't be here.) If
2280 "org.winehq.builtin.text" is not on the pasteboard, then one of the other text formats is
2281 presumably responsible for the promise that we're trying to satisfy, so we keep looking. */
2282 if (format
->natural_format
&& CFArrayContainsValue(types
, range
, format
->natural_format
->type
))
2284 TRACE("Sending WM_RENDERFORMAT message for format %s to hwnd %p\n", debugstr_format(format
->format_id
), hwnd
);
2285 SendMessageW(hwnd
, WM_RENDERFORMAT
, format
->format_id
, 0);
2292 if (types
) CFRelease(types
);