ntdll/tests: Skip test if LdrAddRefDll is missing.
[wine.git] / dlls / winemac.drv / clipboard.c
blob80fd6894cfaf48d788aeda0f340c387dde6eaa92
1 /*
2 * Mac clipboard driver
4 * Copyright 1994 Martin Ayotte
5 * 1996 Alex Korobka
6 * 1999 Noel Borthwick
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
25 #include "config.h"
27 #include "macdrv.h"
28 #include "winuser.h"
29 #include "shellapi.h"
30 #include "shlobj.h"
31 #include "wine/list.h"
32 #include "wine/server.h"
33 #include "wine/unicode.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(clipboard);
39 /**************************************************************************
40 * Types
41 **************************************************************************/
43 typedef struct
45 HWND hwnd_owner;
46 UINT flags;
47 } CLIPBOARDINFO, *LPCLIPBOARDINFO;
49 typedef HANDLE (*DRVIMPORTFUNC)(CFDataRef data);
50 typedef CFDataRef (*DRVEXPORTFUNC)(HANDLE data);
52 typedef struct
54 struct list entry;
55 UINT format_id;
56 CFStringRef type;
57 DRVIMPORTFUNC import_func;
58 DRVEXPORTFUNC export_func;
59 BOOL synthesized;
60 } WINE_CLIPFORMAT;
63 /**************************************************************************
64 * Constants
65 **************************************************************************/
68 /**************************************************************************
69 * Forward Function Declarations
70 **************************************************************************/
72 static HANDLE import_clipboard_data(CFDataRef data);
73 static HANDLE import_bmp_to_bitmap(CFDataRef data);
74 static HANDLE import_bmp_to_dib(CFDataRef data);
75 static HANDLE import_nsfilenames_to_hdrop(CFDataRef data);
76 static HANDLE import_oemtext_to_text(CFDataRef data);
77 static HANDLE import_oemtext_to_unicodetext(CFDataRef data);
78 static HANDLE import_text_to_oemtext(CFDataRef data);
79 static HANDLE import_text_to_unicodetext(CFDataRef data);
80 static HANDLE import_unicodetext_to_oemtext(CFDataRef data);
81 static HANDLE import_unicodetext_to_text(CFDataRef data);
82 static HANDLE import_utf8_to_oemtext(CFDataRef data);
83 static HANDLE import_utf8_to_text(CFDataRef data);
84 static HANDLE import_utf8_to_unicodetext(CFDataRef data);
85 static HANDLE import_utf16_to_oemtext(CFDataRef data);
86 static HANDLE import_utf16_to_text(CFDataRef data);
87 static HANDLE import_utf16_to_unicodetext(CFDataRef data);
89 static CFDataRef export_clipboard_data(HANDLE data);
90 static CFDataRef export_bitmap_to_bmp(HANDLE data);
91 static CFDataRef export_dib_to_bmp(HANDLE data);
92 static CFDataRef export_hdrop_to_filenames(HANDLE data);
93 static CFDataRef export_oemtext_to_utf8(HANDLE data);
94 static CFDataRef export_oemtext_to_utf16(HANDLE data);
95 static CFDataRef export_text_to_utf8(HANDLE data);
96 static CFDataRef export_text_to_utf16(HANDLE data);
97 static CFDataRef export_unicodetext_to_utf8(HANDLE data);
98 static CFDataRef export_unicodetext_to_utf16(HANDLE data);
101 /**************************************************************************
102 * Static Variables
103 **************************************************************************/
105 /* Clipboard formats */
106 static struct list format_list = LIST_INIT(format_list);
108 /* There are two naming schemes involved and we want to have a mapping between
109 them. There are Win32 clipboard format names and there are Mac pasteboard
110 types.
112 The Win32 standard clipboard formats don't have names, but they are associated
113 with Mac pasteboard types through the following tables, which are used to
114 initialize the format_list. Where possible, the standard clipboard formats
115 are mapped to predefined pasteboard type UTIs. Otherwise, we create Wine-
116 specific types of the form "org.winehq.builtin.<format>", where <format> is
117 the name of the symbolic constant for the format minus "CF_" and lowercased.
118 E.g. CF_BITMAP -> org.winehq.builtin.bitmap.
120 Win32 clipboard formats which originate in a Windows program may be registered
121 with an arbitrary name. We construct a Mac pasteboard type from these by
122 prepending "org.winehq.registered." to the registered name.
124 Likewise, Mac pasteboard types which originate in other apps may have
125 arbitrary type strings. We construct a Win32 clipboard format name from
126 these by prepending "org.winehq.mac-type." to the Mac pasteboard type.
128 Summary:
129 Win32 clipboard format names:
130 <none> standard clipboard format; maps via
131 format_list to either a predefined Mac UTI
132 or org.winehq.builtin.<format>.
133 org.winehq.mac-type.<Mac type> representation of Mac type in Win32 land;
134 maps to <Mac type>
135 <other> name registered within Win32 land; maps to
136 org.winehq.registered.<other>
137 Mac pasteboard type names:
138 org.winehq.builtin.<format ID> representation of Win32 standard clipboard
139 format for which there was no corresponding
140 predefined Mac UTI; maps via format_list
141 org.winehq.registered.<format name> representation of Win32 registered
142 clipboard format name; maps to <format name>
143 <other> Mac pasteboard type originating with system
144 or other apps; either maps via format_list
145 to a standard clipboard format or maps to
146 org.winehq.mac-type.<other>
149 static const struct
151 UINT id;
152 CFStringRef type;
153 DRVIMPORTFUNC import;
154 DRVEXPORTFUNC export;
155 BOOL synthesized;
156 } builtin_format_ids[] =
158 { CF_DIBV5, CFSTR("org.winehq.builtin.dibv5"), import_clipboard_data, export_clipboard_data, FALSE },
159 { CF_DIF, CFSTR("org.winehq.builtin.dif"), import_clipboard_data, export_clipboard_data, FALSE },
160 { CF_DSPBITMAP, CFSTR("org.winehq.builtin.dspbitmap"), import_clipboard_data, export_clipboard_data, FALSE },
161 { CF_DSPENHMETAFILE, CFSTR("org.winehq.builtin.dspenhmetafile"), import_clipboard_data, export_clipboard_data, FALSE },
162 { CF_DSPMETAFILEPICT, CFSTR("org.winehq.builtin.dspmetafilepict"), import_clipboard_data, export_clipboard_data, FALSE },
163 { CF_DSPTEXT, CFSTR("org.winehq.builtin.dsptext"), import_clipboard_data, export_clipboard_data, FALSE },
164 { CF_LOCALE, CFSTR("org.winehq.builtin.locale"), import_clipboard_data, export_clipboard_data, FALSE },
165 { CF_OWNERDISPLAY, CFSTR("org.winehq.builtin.ownerdisplay"), import_clipboard_data, export_clipboard_data, FALSE },
166 { CF_PALETTE, CFSTR("org.winehq.builtin.palette"), import_clipboard_data, export_clipboard_data, FALSE },
167 { CF_PENDATA, CFSTR("org.winehq.builtin.pendata"), import_clipboard_data, export_clipboard_data, FALSE },
168 { CF_RIFF, CFSTR("org.winehq.builtin.riff"), import_clipboard_data, export_clipboard_data, FALSE },
169 { CF_SYLK, CFSTR("org.winehq.builtin.sylk"), import_clipboard_data, export_clipboard_data, FALSE },
170 { CF_TIFF, CFSTR("public.tiff"), import_clipboard_data, export_clipboard_data, FALSE },
171 { CF_WAVE, CFSTR("com.microsoft.waveform-audio"), import_clipboard_data, export_clipboard_data, FALSE },
173 { CF_UNICODETEXT, CFSTR("org.winehq.builtin.unicodetext"), import_clipboard_data, export_clipboard_data, FALSE },
174 { CF_TEXT, CFSTR("org.winehq.builtin.unicodetext"), import_unicodetext_to_text, NULL, TRUE },
175 { CF_OEMTEXT, CFSTR("org.winehq.builtin.unicodetext"), import_unicodetext_to_oemtext, NULL, TRUE },
177 { CF_TEXT, CFSTR("org.winehq.builtin.text"), import_clipboard_data, export_clipboard_data, FALSE },
178 { CF_UNICODETEXT, CFSTR("org.winehq.builtin.text"), import_text_to_unicodetext, NULL, TRUE },
179 { CF_OEMTEXT, CFSTR("org.winehq.builtin.text"), import_text_to_oemtext, NULL, TRUE },
181 { CF_OEMTEXT, CFSTR("org.winehq.builtin.oemtext"), import_clipboard_data, export_clipboard_data, FALSE },
182 { CF_UNICODETEXT, CFSTR("org.winehq.builtin.oemtext"), import_oemtext_to_unicodetext, NULL, TRUE },
183 { CF_TEXT, CFSTR("org.winehq.builtin.oemtext"), import_oemtext_to_text, NULL, TRUE },
185 { CF_UNICODETEXT, CFSTR("public.utf8-plain-text"), import_utf8_to_unicodetext, export_unicodetext_to_utf8, TRUE },
186 { CF_TEXT, CFSTR("public.utf8-plain-text"), import_utf8_to_text, export_text_to_utf8, TRUE },
187 { CF_OEMTEXT, CFSTR("public.utf8-plain-text"), import_utf8_to_oemtext, export_oemtext_to_utf8, TRUE },
189 { CF_UNICODETEXT, CFSTR("public.utf16-plain-text"), import_utf16_to_unicodetext, export_unicodetext_to_utf16,TRUE },
190 { CF_TEXT, CFSTR("public.utf16-plain-text"), import_utf16_to_text, export_text_to_utf16, TRUE },
191 { CF_OEMTEXT, CFSTR("public.utf16-plain-text"), import_utf16_to_oemtext, export_oemtext_to_utf16, TRUE },
193 { CF_DIB, CFSTR("org.winehq.builtin.dib"), import_clipboard_data, export_clipboard_data, FALSE },
194 { CF_DIB, CFSTR("com.microsoft.bmp"), import_bmp_to_dib, export_dib_to_bmp, TRUE },
196 { CF_BITMAP, CFSTR("org.winehq.builtin.bitmap"), import_bmp_to_bitmap, export_bitmap_to_bmp, FALSE },
197 { CF_BITMAP, CFSTR("com.microsoft.bmp"), import_bmp_to_bitmap, export_bitmap_to_bmp, TRUE },
199 { CF_HDROP, CFSTR("org.winehq.builtin.hdrop"), import_clipboard_data, export_clipboard_data, FALSE },
200 { CF_HDROP, CFSTR("NSFilenamesPboardType"), import_nsfilenames_to_hdrop, export_hdrop_to_filenames, TRUE },
203 static const WCHAR wszRichTextFormat[] = {'R','i','c','h',' ','T','e','x','t',' ','F','o','r','m','a','t',0};
204 static const WCHAR wszGIF[] = {'G','I','F',0};
205 static const WCHAR wszJFIF[] = {'J','F','I','F',0};
206 static const WCHAR wszPNG[] = {'P','N','G',0};
207 static const WCHAR wszHTMLFormat[] = {'H','T','M','L',' ','F','o','r','m','a','t',0};
208 static const struct
210 LPCWSTR name;
211 CFStringRef type;
212 DRVIMPORTFUNC import;
213 DRVEXPORTFUNC export;
214 } builtin_format_names[] =
216 { wszRichTextFormat, CFSTR("public.rtf"), import_clipboard_data, export_clipboard_data },
217 { wszGIF, CFSTR("com.compuserve.gif"), import_clipboard_data, export_clipboard_data },
218 { wszJFIF, CFSTR("public.jpeg"), import_clipboard_data, export_clipboard_data },
219 { wszPNG, CFSTR("public.png"), import_clipboard_data, export_clipboard_data },
220 { wszHTMLFormat, CFSTR("public.html"), import_clipboard_data, export_clipboard_data },
221 { CFSTR_SHELLURLW, CFSTR("public.url"), import_utf8_to_text, export_text_to_utf8 },
224 /* The prefix prepended to an external Mac pasteboard type to make a Win32 clipboard format name. org.winehq.mac-type. */
225 static const WCHAR mac_type_name_prefix[] = {'o','r','g','.','w','i','n','e','h','q','.','m','a','c','-','t','y','p','e','.',0};
227 /* The prefix prepended to a Win32 clipboard format name to make a Mac pasteboard type. */
228 static const CFStringRef registered_name_type_prefix = CFSTR("org.winehq.registered.");
231 /**************************************************************************
232 * Internal Clipboard implementation methods
233 **************************************************************************/
236 * format_list functions
239 /**************************************************************************
240 * debugstr_format
242 const char *debugstr_format(UINT id)
244 WCHAR buffer[256];
246 if (GetClipboardFormatNameW(id, buffer, 256))
247 return wine_dbg_sprintf("0x%04x %s", id, debugstr_w(buffer));
249 switch (id)
251 #define BUILTIN(id) case id: return #id;
252 BUILTIN(CF_TEXT)
253 BUILTIN(CF_BITMAP)
254 BUILTIN(CF_METAFILEPICT)
255 BUILTIN(CF_SYLK)
256 BUILTIN(CF_DIF)
257 BUILTIN(CF_TIFF)
258 BUILTIN(CF_OEMTEXT)
259 BUILTIN(CF_DIB)
260 BUILTIN(CF_PALETTE)
261 BUILTIN(CF_PENDATA)
262 BUILTIN(CF_RIFF)
263 BUILTIN(CF_WAVE)
264 BUILTIN(CF_UNICODETEXT)
265 BUILTIN(CF_ENHMETAFILE)
266 BUILTIN(CF_HDROP)
267 BUILTIN(CF_LOCALE)
268 BUILTIN(CF_DIBV5)
269 BUILTIN(CF_OWNERDISPLAY)
270 BUILTIN(CF_DSPTEXT)
271 BUILTIN(CF_DSPBITMAP)
272 BUILTIN(CF_DSPMETAFILEPICT)
273 BUILTIN(CF_DSPENHMETAFILE)
274 #undef BUILTIN
275 default: return wine_dbg_sprintf("0x%04x", id);
280 /**************************************************************************
281 * insert_clipboard_format
283 static WINE_CLIPFORMAT *insert_clipboard_format(UINT id, CFStringRef type)
285 WINE_CLIPFORMAT *format;
287 format = HeapAlloc(GetProcessHeap(), 0, sizeof(*format));
289 if (format == NULL)
291 WARN("No more memory for a new format!\n");
292 return NULL;
294 format->format_id = id;
295 format->import_func = import_clipboard_data;
296 format->export_func = export_clipboard_data;
297 format->synthesized = FALSE;
299 if (type)
300 format->type = CFStringCreateCopy(NULL, type);
301 else
303 WCHAR buffer[256];
305 if (!GetClipboardFormatNameW(format->format_id, buffer, sizeof(buffer) / sizeof(buffer[0])))
307 WARN("failed to get name for format %s; error 0x%08x\n", debugstr_format(format->format_id), GetLastError());
308 HeapFree(GetProcessHeap(), 0, format);
309 return NULL;
312 if (!strncmpW(buffer, mac_type_name_prefix, strlenW(mac_type_name_prefix)))
314 const WCHAR *p = buffer + strlenW(mac_type_name_prefix);
315 format->type = CFStringCreateWithCharacters(NULL, (UniChar*)p, strlenW(p));
317 else
319 format->type = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%S"),
320 registered_name_type_prefix, buffer);
324 list_add_tail(&format_list, &format->entry);
326 TRACE("Registering format %s type %s\n", debugstr_format(format->format_id),
327 debugstr_cf(format->type));
329 return format;
333 /**************************************************************************
334 * register_format
336 * Register a custom Mac clipboard format.
338 static WINE_CLIPFORMAT* register_format(UINT id, CFStringRef type)
340 WINE_CLIPFORMAT *format;
342 /* walk format chain to see if it's already registered */
343 LIST_FOR_EACH_ENTRY(format, &format_list, WINE_CLIPFORMAT, entry)
344 if (format->format_id == id) return format;
346 return insert_clipboard_format(id, type);
350 /**************************************************************************
351 * format_for_type
353 static WINE_CLIPFORMAT* format_for_type(WINE_CLIPFORMAT *current, CFStringRef type)
355 struct list *ptr = current ? &current->entry : &format_list;
356 WINE_CLIPFORMAT *format = NULL;
358 TRACE("current %p/%s type %s\n", current, debugstr_format(current ? current->format_id : 0), debugstr_cf(type));
360 while ((ptr = list_next(&format_list, ptr)))
362 format = LIST_ENTRY(ptr, WINE_CLIPFORMAT, entry);
363 if (CFEqual(format->type, type))
365 TRACE(" -> %p/%s\n", format, debugstr_format(format->format_id));
366 return format;
370 if (!current)
372 LPWSTR name;
374 if (CFStringHasPrefix(type, CFSTR("org.winehq.builtin.")))
376 ERR("Shouldn't happen. Built-in type %s should have matched something in format list.\n",
377 debugstr_cf(type));
378 return NULL;
380 else if (CFStringHasPrefix(type, registered_name_type_prefix))
382 int len = CFStringGetLength(type) - CFStringGetLength(registered_name_type_prefix);
383 name = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
384 CFStringGetCharacters(type, CFRangeMake(CFStringGetLength(registered_name_type_prefix), len),
385 (UniChar*)name);
386 name[len] = 0;
388 else
390 int len = strlenW(mac_type_name_prefix) + CFStringGetLength(type);
391 name = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
392 memcpy(name, mac_type_name_prefix, sizeof(mac_type_name_prefix));
393 CFStringGetCharacters(type, CFRangeMake(0, CFStringGetLength(type)),
394 (UniChar*)name + strlenW(mac_type_name_prefix));
395 name[len] = 0;
398 format = register_format(RegisterClipboardFormatW(name), type);
399 if (!format)
400 ERR("Failed to register format for type %s name %s\n", debugstr_cf(type), debugstr_w(name));
402 HeapFree(GetProcessHeap(), 0, name);
405 TRACE(" -> %p/%s\n", format, debugstr_format(format ? format->format_id : 0));
406 return format;
410 /**************************************************************************
411 * convert_text
413 * Convert string data between code pages or to/from wide characters. The
414 * special value of (UINT)-1 for a code page indicates to use wide
415 * characters.
417 static HANDLE convert_text(const void *src, int src_len, UINT src_cp, UINT dest_cp)
419 HANDLE ret = NULL;
420 const WCHAR *wstr;
421 int wstr_len;
422 HANDLE handle;
423 char *p;
425 if (src_cp == (UINT)-1)
427 wstr = src;
428 wstr_len = src_len / sizeof(WCHAR);
430 else
432 WCHAR *temp;
434 wstr_len = MultiByteToWideChar(src_cp, 0, src, src_len, NULL, 0);
435 if (!src_len || ((const char*)src)[src_len - 1]) wstr_len += 1;
436 temp = HeapAlloc(GetProcessHeap(), 0, wstr_len * sizeof(WCHAR));
437 MultiByteToWideChar(src_cp, 0, src, src_len, temp, wstr_len);
438 temp[wstr_len - 1] = 0;
439 wstr = temp;
442 if (dest_cp == (UINT)-1)
444 handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, wstr_len * sizeof(WCHAR));
445 if (handle && (p = GlobalLock(handle)))
447 memcpy(p, wstr, wstr_len * sizeof(WCHAR));
448 GlobalUnlock(handle);
449 ret = handle;
452 else
454 INT len;
456 len = WideCharToMultiByte(dest_cp, 0, wstr, wstr_len, NULL, 0, NULL, NULL);
457 if (!wstr_len || wstr[wstr_len - 1]) len += 1;
458 handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, len);
460 if (handle && (p = GlobalLock(handle)))
462 WideCharToMultiByte(dest_cp, 0, wstr, wstr_len, p, len, NULL, NULL);
463 p[len - 1] = 0;
464 GlobalUnlock(handle);
465 ret = handle;
469 return ret;
473 /**************************************************************************
474 * convert_unicodetext_to_codepage
476 static HANDLE convert_unicodetext_to_codepage(HANDLE unicode_handle, UINT cp)
478 LPWSTR unicode_string = GlobalLock(unicode_handle);
479 HANDLE ret = NULL;
481 if (unicode_string)
483 ret = convert_text(unicode_string, GlobalSize(unicode_handle), -1, cp);
484 GlobalUnlock(unicode_handle);
487 return ret;
491 /***********************************************************************
492 * bitmap_info_size
494 * Return the size of the bitmap info structure including color table.
496 static int bitmap_info_size(const BITMAPINFO *info, WORD coloruse)
498 unsigned int colors, size, masks = 0;
500 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
502 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER*)info;
503 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
504 return sizeof(BITMAPCOREHEADER) + colors *
505 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
507 else /* assume BITMAPINFOHEADER */
509 colors = info->bmiHeader.biClrUsed;
510 if (!colors && (info->bmiHeader.biBitCount <= 8))
511 colors = 1 << info->bmiHeader.biBitCount;
512 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
513 size = max(info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD));
514 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
519 /***********************************************************************
520 * create_dib_from_bitmap
522 * Allocates a packed DIB and copies the bitmap data into it.
524 static HGLOBAL create_dib_from_bitmap(HBITMAP hBmp)
526 BITMAP bmp;
527 HDC hdc;
528 HGLOBAL hPackedDIB;
529 LPBYTE pPackedDIB;
530 LPBITMAPINFOHEADER pbmiHeader;
531 unsigned int cDataSize, cPackedSize, OffsetBits;
532 int nLinesCopied;
534 if (!GetObjectW(hBmp, sizeof(bmp), &bmp)) return 0;
537 * A packed DIB contains a BITMAPINFO structure followed immediately by
538 * an optional color palette and the pixel data.
541 /* Calculate the size of the packed DIB */
542 cDataSize = abs(bmp.bmHeight) * (((bmp.bmWidth * bmp.bmBitsPixel + 31) / 8) & ~3);
543 cPackedSize = sizeof(BITMAPINFOHEADER)
544 + ((bmp.bmBitsPixel <= 8) ? (sizeof(RGBQUAD) * (1 << bmp.bmBitsPixel)) : 0)
545 + cDataSize;
546 /* Get the offset to the bits */
547 OffsetBits = cPackedSize - cDataSize;
549 /* Allocate the packed DIB */
550 TRACE("\tAllocating packed DIB of size %d\n", cPackedSize);
551 hPackedDIB = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, cPackedSize);
552 if (!hPackedDIB)
554 WARN("Could not allocate packed DIB!\n");
555 return 0;
558 /* A packed DIB starts with a BITMAPINFOHEADER */
559 pPackedDIB = GlobalLock(hPackedDIB);
560 pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
562 /* Init the BITMAPINFOHEADER */
563 pbmiHeader->biSize = sizeof(BITMAPINFOHEADER);
564 pbmiHeader->biWidth = bmp.bmWidth;
565 pbmiHeader->biHeight = bmp.bmHeight;
566 pbmiHeader->biPlanes = 1;
567 pbmiHeader->biBitCount = bmp.bmBitsPixel;
568 pbmiHeader->biCompression = BI_RGB;
569 pbmiHeader->biSizeImage = 0;
570 pbmiHeader->biXPelsPerMeter = pbmiHeader->biYPelsPerMeter = 0;
571 pbmiHeader->biClrUsed = 0;
572 pbmiHeader->biClrImportant = 0;
574 /* Retrieve the DIB bits from the bitmap and fill in the
575 * DIB color table if present */
576 hdc = GetDC(0);
577 nLinesCopied = GetDIBits(hdc, /* Handle to device context */
578 hBmp, /* Handle to bitmap */
579 0, /* First scan line to set in dest bitmap */
580 bmp.bmHeight, /* Number of scan lines to copy */
581 pPackedDIB + OffsetBits, /* [out] Address of array for bitmap bits */
582 (LPBITMAPINFO) pbmiHeader, /* [out] Address of BITMAPINFO structure */
583 0); /* RGB or palette index */
584 GlobalUnlock(hPackedDIB);
585 ReleaseDC(0, hdc);
587 /* Cleanup if GetDIBits failed */
588 if (nLinesCopied != bmp.bmHeight)
590 TRACE("\tGetDIBits returned %d. Actual lines=%d\n", nLinesCopied, bmp.bmHeight);
591 GlobalFree(hPackedDIB);
592 hPackedDIB = 0;
594 return hPackedDIB;
598 /**************************************************************************
599 * import_clipboard_data
601 * Generic import clipboard data routine.
603 static HANDLE import_clipboard_data(CFDataRef data)
605 HANDLE data_handle = NULL;
607 size_t len = CFDataGetLength(data);
608 if (len)
610 LPVOID p;
612 /* Turn on the DDESHARE flag to enable shared 32 bit memory */
613 data_handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, len);
614 if (!data_handle)
615 return NULL;
617 if ((p = GlobalLock(data_handle)))
619 memcpy(p, CFDataGetBytePtr(data), len);
620 GlobalUnlock(data_handle);
622 else
624 GlobalFree(data_handle);
625 data_handle = NULL;
629 return data_handle;
633 /**************************************************************************
634 * import_bmp_to_bitmap
636 * Import BMP data, converting to CF_BITMAP format.
638 static HANDLE import_bmp_to_bitmap(CFDataRef data)
640 HANDLE ret = 0;
641 HANDLE dib = import_bmp_to_dib(data);
642 BITMAPINFO *bmi;
644 if (dib && (bmi = GlobalLock(dib)))
646 HDC hdc;
647 unsigned int offset;
649 hdc = GetDC(NULL);
651 offset = bitmap_info_size(bmi, DIB_RGB_COLORS);
653 ret = CreateDIBitmap(hdc, &bmi->bmiHeader, CBM_INIT, (LPBYTE)bmi + offset,
654 bmi, DIB_RGB_COLORS);
656 GlobalUnlock(dib);
657 ReleaseDC(NULL, hdc);
660 GlobalFree(dib);
661 return ret;
665 /**************************************************************************
666 * import_bmp_to_dib
668 * Import BMP data, converting to CF_DIB format. This just entails
669 * stripping the BMP file format header.
671 static HANDLE import_bmp_to_dib(CFDataRef data)
673 HANDLE ret = 0;
674 BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)CFDataGetBytePtr(data);
675 CFIndex len = CFDataGetLength(data);
677 if (len >= sizeof(*bfh) + sizeof(BITMAPCOREHEADER) &&
678 bfh->bfType == 0x4d42 /* "BM" */)
680 BITMAPINFO *bmi = (BITMAPINFO*)(bfh + 1);
681 BYTE* p;
683 len -= sizeof(*bfh);
684 ret = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, len);
685 if (!ret || !(p = GlobalLock(ret)))
687 GlobalFree(ret);
688 return 0;
691 memcpy(p, bmi, len);
692 GlobalUnlock(ret);
695 return ret;
699 /**************************************************************************
700 * import_nsfilenames_to_hdrop
702 * Import NSFilenamesPboardType data, converting the property-list-
703 * serialized array of path strings to CF_HDROP.
705 static HANDLE import_nsfilenames_to_hdrop(CFDataRef data)
707 HDROP hdrop = NULL;
708 CFArrayRef names;
709 CFIndex count, i;
710 size_t len;
711 char *buffer = NULL;
712 WCHAR **paths = NULL;
713 DROPFILES* dropfiles;
714 UniChar* p;
716 TRACE("data %s\n", debugstr_cf(data));
718 names = (CFArrayRef)CFPropertyListCreateWithData(NULL, data, kCFPropertyListImmutable,
719 NULL, NULL);
720 if (!names || CFGetTypeID(names) != CFArrayGetTypeID())
722 WARN("failed to interpret data as a CFArray\n");
723 goto done;
726 count = CFArrayGetCount(names);
728 len = 0;
729 for (i = 0; i < count; i++)
731 CFIndex this_len;
732 CFStringRef name = (CFStringRef)CFArrayGetValueAtIndex(names, i);
733 TRACE(" %s\n", debugstr_cf(name));
734 if (CFGetTypeID(name) != CFStringGetTypeID())
736 WARN("non-string in array\n");
737 goto done;
740 this_len = CFStringGetMaximumSizeOfFileSystemRepresentation(name);
741 if (this_len > len)
742 len = this_len;
745 buffer = HeapAlloc(GetProcessHeap(), 0, len);
746 if (!buffer)
748 WARN("failed to allocate buffer for file-system representations\n");
749 goto done;
752 paths = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, count * sizeof(paths[0]));
753 if (!paths)
755 WARN("failed to allocate array of DOS paths\n");
756 goto done;
759 for (i = 0; i < count; i++)
761 CFStringRef name = (CFStringRef)CFArrayGetValueAtIndex(names, i);
762 if (!CFStringGetFileSystemRepresentation(name, buffer, len))
764 WARN("failed to get file-system representation for %s\n", debugstr_cf(name));
765 goto done;
767 paths[i] = wine_get_dos_file_name(buffer);
768 if (!paths[i])
770 WARN("failed to get DOS path for %s\n", debugstr_a(buffer));
771 goto done;
775 len = 1; /* for the terminating null */
776 for (i = 0; i < count; i++)
777 len += strlenW(paths[i]) + 1;
779 hdrop = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, sizeof(*dropfiles) + len * sizeof(WCHAR));
780 if (!hdrop || !(dropfiles = GlobalLock(hdrop)))
782 WARN("failed to allocate HDROP\n");
783 GlobalFree(hdrop);
784 hdrop = NULL;
785 goto done;
788 dropfiles->pFiles = sizeof(*dropfiles);
789 dropfiles->pt.x = 0;
790 dropfiles->pt.y = 0;
791 dropfiles->fNC = FALSE;
792 dropfiles->fWide = TRUE;
794 p = (WCHAR*)(dropfiles + 1);
795 for (i = 0; i < count; i++)
797 strcpyW(p, paths[i]);
798 p += strlenW(p) + 1;
800 *p = 0;
802 GlobalUnlock(hdrop);
804 done:
805 if (paths)
807 for (i = 0; i < count; i++)
808 HeapFree(GetProcessHeap(), 0, paths[i]);
809 HeapFree(GetProcessHeap(), 0, paths);
811 HeapFree(GetProcessHeap(), 0, buffer);
812 if (names) CFRelease(names);
813 return hdrop;
817 /**************************************************************************
818 * import_oemtext_to_text
820 * Import CF_OEMTEXT data, converting the string to CF_TEXT.
822 static HANDLE import_oemtext_to_text(CFDataRef data)
824 return convert_text(CFDataGetBytePtr(data), CFDataGetLength(data), CP_OEMCP, CP_ACP);
828 /**************************************************************************
829 * import_oemtext_to_unicodetext
831 * Import CF_OEMTEXT data, converting the string to CF_UNICODETEXT.
833 static HANDLE import_oemtext_to_unicodetext(CFDataRef data)
835 return convert_text(CFDataGetBytePtr(data), CFDataGetLength(data), CP_OEMCP, -1);
839 /**************************************************************************
840 * import_text_to_oemtext
842 * Import CF_TEXT data, converting the string to CF_OEMTEXT.
844 static HANDLE import_text_to_oemtext(CFDataRef data)
846 return convert_text(CFDataGetBytePtr(data), CFDataGetLength(data), CP_ACP, CP_OEMCP);
850 /**************************************************************************
851 * import_text_to_unicodetext
853 * Import CF_TEXT data, converting the string to CF_UNICODETEXT.
855 static HANDLE import_text_to_unicodetext(CFDataRef data)
857 return convert_text(CFDataGetBytePtr(data), CFDataGetLength(data), CP_ACP, -1);
861 /**************************************************************************
862 * import_unicodetext_to_oemtext
864 * Import a CF_UNICODETEXT string, converting the string to CF_OEMTEXT.
866 static HANDLE import_unicodetext_to_oemtext(CFDataRef data)
868 return convert_text(CFDataGetBytePtr(data), CFDataGetLength(data), -1, CP_OEMCP);
872 /**************************************************************************
873 * import_unicodetext_to_text
875 * Import a CF_UNICODETEXT string, converting the string to CF_TEXT.
877 static HANDLE import_unicodetext_to_text(CFDataRef data)
879 return convert_text(CFDataGetBytePtr(data), CFDataGetLength(data), -1, CP_ACP);
883 /**************************************************************************
884 * import_utf8_to_oemtext
886 * Import a UTF-8 string, converting the string to CF_OEMTEXT.
888 static HANDLE import_utf8_to_oemtext(CFDataRef data)
890 HANDLE unicode_handle = import_utf8_to_unicodetext(data);
891 HANDLE ret = convert_unicodetext_to_codepage(unicode_handle, CP_OEMCP);
893 GlobalFree(unicode_handle);
894 return ret;
898 /**************************************************************************
899 * import_utf8_to_text
901 * Import a UTF-8 string, converting the string to CF_TEXT.
903 static HANDLE import_utf8_to_text(CFDataRef data)
905 HANDLE unicode_handle = import_utf8_to_unicodetext(data);
906 HANDLE ret = convert_unicodetext_to_codepage(unicode_handle, CP_ACP);
908 GlobalFree(unicode_handle);
909 return ret;
913 /**************************************************************************
914 * import_utf8_to_unicodetext
916 * Import a UTF-8 string, converting the string to CF_UNICODETEXT.
918 static HANDLE import_utf8_to_unicodetext(CFDataRef data)
920 const BYTE *src;
921 unsigned long data_len;
922 unsigned long new_lines = 0;
923 LPSTR dst;
924 unsigned long i, j;
925 HANDLE unicode_handle = NULL;
927 src = CFDataGetBytePtr(data);
928 data_len = CFDataGetLength(data);
929 for (i = 0; i < data_len; i++)
931 if (src[i] == '\n')
932 new_lines++;
935 if ((dst = HeapAlloc(GetProcessHeap(), 0, data_len + new_lines + 1)))
937 UINT count;
939 for (i = 0, j = 0; i < data_len; i++)
941 if (src[i] == '\n')
942 dst[j++] = '\r';
944 dst[j++] = src[i];
946 dst[j] = 0;
948 count = MultiByteToWideChar(CP_UTF8, 0, dst, -1, NULL, 0);
949 unicode_handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, count * sizeof(WCHAR));
951 if (unicode_handle)
953 WCHAR *textW = GlobalLock(unicode_handle);
954 MultiByteToWideChar(CP_UTF8, 0, dst, -1, textW, count);
955 GlobalUnlock(unicode_handle);
958 HeapFree(GetProcessHeap(), 0, dst);
961 return unicode_handle;
965 /**************************************************************************
966 * import_utf16_to_oemtext
968 * Import a UTF-16 string, converting the string to CF_OEMTEXT.
970 static HANDLE import_utf16_to_oemtext(CFDataRef data)
972 HANDLE unicode_handle = import_utf16_to_unicodetext(data);
973 HANDLE ret = convert_unicodetext_to_codepage(unicode_handle, CP_OEMCP);
975 GlobalFree(unicode_handle);
976 return ret;
980 /**************************************************************************
981 * import_utf16_to_text
983 * Import a UTF-16 string, converting the string to CF_TEXT.
985 static HANDLE import_utf16_to_text(CFDataRef data)
987 HANDLE unicode_handle = import_utf16_to_unicodetext(data);
988 HANDLE ret = convert_unicodetext_to_codepage(unicode_handle, CP_ACP);
990 GlobalFree(unicode_handle);
991 return ret;
995 /**************************************************************************
996 * import_utf16_to_unicodetext
998 * Import a UTF-8 string, converting the string to CF_UNICODETEXT.
1000 static HANDLE import_utf16_to_unicodetext(CFDataRef data)
1002 const WCHAR *src;
1003 unsigned long data_len;
1004 unsigned long new_lines = 0;
1005 LPWSTR dst;
1006 unsigned long i, j;
1007 HANDLE unicode_handle;
1009 src = (const WCHAR *)CFDataGetBytePtr(data);
1010 data_len = CFDataGetLength(data);
1011 for (i = 0; i < data_len; i++)
1013 if (src[i] == '\n')
1014 new_lines++;
1017 if ((unicode_handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, (data_len + new_lines + 1) * sizeof(WCHAR))))
1019 dst = GlobalLock(unicode_handle);
1021 for (i = 0, j = 0; i < data_len; i++)
1023 if (src[i] == '\n')
1024 dst[j++] = '\r';
1026 dst[j++] = src[i];
1028 dst[j] = 0;
1030 GlobalUnlock(unicode_handle);
1033 return unicode_handle;
1037 /**************************************************************************
1038 * export_clipboard_data
1040 * Generic export clipboard data routine.
1042 static CFDataRef export_clipboard_data(HANDLE data)
1044 CFDataRef ret;
1045 UINT len;
1046 LPVOID src;
1048 len = GlobalSize(data);
1049 src = GlobalLock(data);
1050 if (!src) return NULL;
1052 ret = CFDataCreate(NULL, src, len);
1053 GlobalUnlock(data);
1055 return ret;
1059 /**************************************************************************
1060 * export_bitmap_to_bmp
1062 * Export CF_BITMAP to BMP file format.
1064 static CFDataRef export_bitmap_to_bmp(HANDLE data)
1066 CFDataRef ret = NULL;
1067 HGLOBAL dib;
1069 dib = create_dib_from_bitmap(data);
1070 if (dib)
1072 ret = export_dib_to_bmp(dib);
1073 GlobalFree(dib);
1076 return ret;
1080 /**************************************************************************
1081 * export_codepage_to_utf8
1083 * Export string data in a specified codepage to UTF-8.
1085 static CFDataRef export_codepage_to_utf8(HANDLE data, UINT cp)
1087 CFDataRef ret = NULL;
1088 const char* str;
1090 if ((str = GlobalLock(data)))
1092 HANDLE unicode = convert_text(str, GlobalSize(data), cp, -1);
1094 ret = export_unicodetext_to_utf8(unicode);
1096 GlobalFree(unicode);
1097 GlobalUnlock(data);
1100 return ret;
1104 /**************************************************************************
1105 * export_codepage_to_utf16
1107 * Export string data in a specified codepage to UTF-16.
1109 static CFDataRef export_codepage_to_utf16(HANDLE data, UINT cp)
1111 CFDataRef ret = NULL;
1112 const char* str;
1114 if ((str = GlobalLock(data)))
1116 HANDLE unicode = convert_text(str, GlobalSize(data), cp, -1);
1118 ret = export_unicodetext_to_utf16(unicode);
1120 GlobalFree(unicode);
1121 GlobalUnlock(data);
1124 return ret;
1128 /**************************************************************************
1129 * export_dib_to_bmp
1131 * Export CF_DIB to BMP file format. This just entails prepending a BMP
1132 * file format header to the data.
1134 static CFDataRef export_dib_to_bmp(HANDLE data)
1136 CFMutableDataRef ret = NULL;
1137 BYTE *dibdata;
1138 CFIndex len;
1139 BITMAPFILEHEADER bfh;
1141 dibdata = GlobalLock(data);
1142 if (!dibdata)
1143 return NULL;
1145 len = sizeof(bfh) + GlobalSize(data);
1146 ret = CFDataCreateMutable(NULL, len);
1147 if (ret)
1149 bfh.bfType = 0x4d42; /* "BM" */
1150 bfh.bfSize = len;
1151 bfh.bfReserved1 = 0;
1152 bfh.bfReserved2 = 0;
1153 bfh.bfOffBits = sizeof(bfh) + bitmap_info_size((BITMAPINFO*)dibdata, DIB_RGB_COLORS);
1154 CFDataAppendBytes(ret, (UInt8*)&bfh, sizeof(bfh));
1156 /* rest of bitmap is the same as the packed dib */
1157 CFDataAppendBytes(ret, (UInt8*)dibdata, len - sizeof(bfh));
1160 GlobalUnlock(data);
1162 return ret;
1166 /**************************************************************************
1167 * export_hdrop_to_filenames
1169 * Export CF_HDROP to NSFilenamesPboardType data, which is a CFArray of
1170 * CFStrings (holding Unix paths) which is serialized as a property list.
1172 static CFDataRef export_hdrop_to_filenames(HANDLE data)
1174 CFDataRef ret = NULL;
1175 DROPFILES *dropfiles;
1176 CFMutableArrayRef filenames = NULL;
1177 void *p;
1178 WCHAR *buffer = NULL;
1179 size_t buffer_len = 0;
1181 TRACE("data %p\n", data);
1183 if (!(dropfiles = GlobalLock(data)))
1185 WARN("failed to lock data %p\n", data);
1186 goto done;
1189 filenames = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
1190 if (!filenames)
1192 WARN("failed to create filenames array\n");
1193 goto done;
1196 p = (char*)dropfiles + dropfiles->pFiles;
1197 while (dropfiles->fWide ? *(WCHAR*)p : *(char*)p)
1199 char *unixname;
1200 CFStringRef filename;
1202 TRACE(" %s\n", dropfiles->fWide ? debugstr_w(p) : debugstr_a(p));
1204 if (dropfiles->fWide)
1205 unixname = wine_get_unix_file_name(p);
1206 else
1208 int len = MultiByteToWideChar(CP_ACP, 0, p, -1, NULL, 0);
1209 if (len)
1211 if (len > buffer_len)
1213 HeapFree(GetProcessHeap(), 0, buffer);
1214 buffer_len = len * 2;
1215 buffer = HeapAlloc(GetProcessHeap(), 0, buffer_len * sizeof(*buffer));
1218 MultiByteToWideChar(CP_ACP, 0, p, -1, buffer, buffer_len);
1219 unixname = wine_get_unix_file_name(buffer);
1221 else
1222 unixname = NULL;
1224 if (!unixname)
1226 WARN("failed to convert DOS path to Unix: %s\n",
1227 dropfiles->fWide ? debugstr_w(p) : debugstr_a(p));
1228 goto done;
1231 if (dropfiles->fWide)
1232 p = (WCHAR*)p + strlenW(p) + 1;
1233 else
1234 p = (char*)p + strlen(p) + 1;
1236 filename = CFStringCreateWithFileSystemRepresentation(NULL, unixname);
1237 HeapFree(GetProcessHeap(), 0, unixname);
1238 if (!filename)
1240 WARN("failed to create CFString from Unix path %s\n", debugstr_a(unixname));
1241 goto done;
1244 CFArrayAppendValue(filenames, filename);
1245 CFRelease(filename);
1248 ret = CFPropertyListCreateData(NULL, filenames, kCFPropertyListXMLFormat_v1_0, 0, NULL);
1250 done:
1251 HeapFree(GetProcessHeap(), 0, buffer);
1252 GlobalUnlock(data);
1253 if (filenames) CFRelease(filenames);
1254 TRACE(" -> %s\n", debugstr_cf(ret));
1255 return ret;
1259 /**************************************************************************
1260 * export_oemtext_to_utf8
1262 * Export CF_OEMTEXT to UTF-8.
1264 static CFDataRef export_oemtext_to_utf8(HANDLE data)
1266 return export_codepage_to_utf8(data, CP_OEMCP);
1270 /**************************************************************************
1271 * export_oemtext_to_utf16
1273 * Export CF_OEMTEXT to UTF-16.
1275 static CFDataRef export_oemtext_to_utf16(HANDLE data)
1277 return export_codepage_to_utf16(data, CP_OEMCP);
1281 /**************************************************************************
1282 * export_text_to_utf8
1284 * Export CF_TEXT to UTF-8.
1286 static CFDataRef export_text_to_utf8(HANDLE data)
1288 return export_codepage_to_utf8(data, CP_ACP);
1292 /**************************************************************************
1293 * export_text_to_utf16
1295 * Export CF_TEXT to UTF-16.
1297 static CFDataRef export_text_to_utf16(HANDLE data)
1299 return export_codepage_to_utf16(data, CP_ACP);
1303 /**************************************************************************
1304 * export_unicodetext_to_utf8
1306 * Export CF_UNICODETEXT to UTF-8.
1308 static CFDataRef export_unicodetext_to_utf8(HANDLE data)
1310 CFMutableDataRef ret;
1311 LPVOID src;
1312 INT dst_len;
1314 src = GlobalLock(data);
1315 if (!src) return NULL;
1317 dst_len = WideCharToMultiByte(CP_UTF8, 0, src, -1, NULL, 0, NULL, NULL);
1318 if (dst_len) dst_len--; /* Leave off null terminator. */
1319 ret = CFDataCreateMutable(NULL, dst_len);
1320 if (ret)
1322 LPSTR dst;
1323 int i, j;
1325 CFDataSetLength(ret, dst_len);
1326 dst = (LPSTR)CFDataGetMutableBytePtr(ret);
1327 WideCharToMultiByte(CP_UTF8, 0, src, -1, dst, dst_len, NULL, NULL);
1329 /* Remove carriage returns */
1330 for (i = 0, j = 0; i < dst_len; i++)
1332 if (dst[i] == '\r' &&
1333 (i + 1 >= dst_len || dst[i + 1] == '\n' || dst[i + 1] == '\0'))
1334 continue;
1335 dst[j++] = dst[i];
1337 CFDataSetLength(ret, j);
1339 GlobalUnlock(data);
1341 return ret;
1345 /**************************************************************************
1346 * export_unicodetext_to_utf16
1348 * Export CF_UNICODETEXT to UTF-16.
1350 static CFDataRef export_unicodetext_to_utf16(HANDLE data)
1352 CFMutableDataRef ret;
1353 const WCHAR *src;
1354 INT dst_len;
1356 src = GlobalLock(data);
1357 if (!src) return NULL;
1359 dst_len = GlobalSize(data) / sizeof(WCHAR);
1360 if (dst_len) dst_len--; /* Leave off null terminator. */
1361 ret = CFDataCreateMutable(NULL, dst_len);
1362 if (ret)
1364 LPWSTR dst;
1365 int i, j;
1367 CFDataSetLength(ret, dst_len);
1368 dst = (LPWSTR)CFDataGetMutableBytePtr(ret);
1370 /* Remove carriage returns */
1371 for (i = 0, j = 0; i < dst_len; i++)
1373 if (src[i] == '\r' &&
1374 (i + 1 >= dst_len || src[i + 1] == '\n' || src[i + 1] == '\0'))
1375 continue;
1376 dst[j++] = src[i];
1378 CFDataSetLength(ret, j);
1380 GlobalUnlock(data);
1382 return ret;
1386 /**************************************************************************
1387 * get_clipboard_info
1389 static BOOL get_clipboard_info(LPCLIPBOARDINFO cbinfo)
1391 BOOL ret = FALSE;
1393 SERVER_START_REQ(set_clipboard_info)
1395 req->flags = 0;
1397 if (wine_server_call_err(req))
1399 ERR("Failed to get clipboard owner.\n");
1401 else
1403 cbinfo->hwnd_owner = wine_server_ptr_handle(reply->old_owner);
1404 cbinfo->flags = reply->flags;
1406 ret = TRUE;
1409 SERVER_END_REQ;
1411 return ret;
1415 /**************************************************************************
1416 * release_ownership
1418 static BOOL release_ownership(void)
1420 BOOL ret = FALSE;
1422 SERVER_START_REQ(set_clipboard_info)
1424 req->flags = SET_CB_RELOWNER | SET_CB_SEQNO;
1426 if (wine_server_call_err(req))
1427 ERR("Failed to set clipboard.\n");
1428 else
1429 ret = TRUE;
1431 SERVER_END_REQ;
1433 return ret;
1437 /**************************************************************************
1438 * macdrv_get_pasteboard_data
1440 HANDLE macdrv_get_pasteboard_data(CFTypeRef pasteboard, UINT desired_format)
1442 CFArrayRef types;
1443 CFIndex count;
1444 CFIndex i;
1445 CFStringRef type, best_type;
1446 WINE_CLIPFORMAT* best_format = NULL;
1447 HANDLE data = NULL;
1449 TRACE("pasteboard %p, desired_format %s\n", pasteboard, debugstr_format(desired_format));
1451 types = macdrv_copy_pasteboard_types(pasteboard);
1452 if (!types)
1454 WARN("Failed to copy pasteboard types\n");
1455 return NULL;
1458 count = CFArrayGetCount(types);
1459 TRACE("got %ld types\n", count);
1461 for (i = 0; (!best_format || best_format->synthesized) && i < count; i++)
1463 WINE_CLIPFORMAT* format;
1465 type = CFArrayGetValueAtIndex(types, i);
1467 format = NULL;
1468 while ((!best_format || best_format->synthesized) && (format = format_for_type(format, type)))
1470 TRACE("for type %s got format %p/%s\n", debugstr_cf(type), format, debugstr_format(format ? format->format_id : 0));
1472 if (format->format_id == desired_format)
1474 /* The best format is the matching one which is not synthesized. Failing that,
1475 the best format is the first matching synthesized format. */
1476 if (!format->synthesized || !best_format)
1478 best_type = type;
1479 best_format = format;
1485 if (best_format)
1487 CFDataRef pasteboard_data = macdrv_copy_pasteboard_data(pasteboard, best_type);
1489 TRACE("got pasteboard data for type %s: %s\n", debugstr_cf(best_type), debugstr_cf(pasteboard_data));
1491 if (pasteboard_data)
1493 data = best_format->import_func(pasteboard_data);
1494 CFRelease(pasteboard_data);
1498 CFRelease(types);
1499 TRACE(" -> %p\n", data);
1500 return data;
1504 /**************************************************************************
1505 * macdrv_pasteboard_has_format
1507 BOOL macdrv_pasteboard_has_format(CFTypeRef pasteboard, UINT desired_format)
1509 CFArrayRef types;
1510 int count;
1511 UINT i;
1512 BOOL found = FALSE;
1514 TRACE("pasteboard %p, desired_format %s\n", pasteboard, debugstr_format(desired_format));
1516 types = macdrv_copy_pasteboard_types(pasteboard);
1517 if (!types)
1519 WARN("Failed to copy pasteboard types\n");
1520 return FALSE;
1523 count = CFArrayGetCount(types);
1524 TRACE("got %d types\n", count);
1526 for (i = 0; !found && i < count; i++)
1528 CFStringRef type = CFArrayGetValueAtIndex(types, i);
1529 WINE_CLIPFORMAT* format;
1531 format = NULL;
1532 while (!found && (format = format_for_type(format, type)))
1534 TRACE("for type %s got format %s\n", debugstr_cf(type), debugstr_format(format->format_id));
1536 if (format->format_id == desired_format)
1537 found = TRUE;
1541 CFRelease(types);
1542 TRACE(" -> %d\n", found);
1543 return found;
1547 /**************************************************************************
1548 * macdrv_copy_pasteboard_formats
1550 CFArrayRef macdrv_copy_pasteboard_formats(CFTypeRef pasteboard)
1552 CFArrayRef types;
1553 CFIndex count;
1554 CFMutableArrayRef formats;
1555 CFIndex i;
1557 TRACE("pasteboard %p\n", pasteboard);
1559 types = macdrv_copy_pasteboard_types(pasteboard);
1560 if (!types)
1562 WARN("Failed to copy pasteboard types\n");
1563 return NULL;
1566 count = CFArrayGetCount(types);
1567 TRACE("got %ld types\n", count);
1569 if (!count)
1571 CFRelease(types);
1572 return NULL;
1575 formats = CFArrayCreateMutable(NULL, 0, NULL);
1576 if (!formats)
1578 WARN("Failed to allocate formats array\n");
1579 CFRelease(types);
1580 return NULL;
1583 for (i = 0; i < count; i++)
1585 CFStringRef type = CFArrayGetValueAtIndex(types, i);
1586 WINE_CLIPFORMAT* format;
1588 format = NULL;
1589 while ((format = format_for_type(format, type)))
1591 TRACE("for type %s got format %p/%s\n", debugstr_cf(type), format, debugstr_format(format->format_id));
1593 if (format->synthesized)
1595 /* Don't override a real value with a synthesized value. */
1596 if (!CFArrayContainsValue(formats, CFRangeMake(0, CFArrayGetCount(formats)), (void*)format->format_id))
1597 CFArrayAppendValue(formats, (void*)format->format_id);
1599 else
1601 /* If the type was already in the array, it must have been synthesized
1602 because this one's real. Remove the synthesized entry in favor of
1603 this one. */
1604 CFIndex index = CFArrayGetFirstIndexOfValue(formats, CFRangeMake(0, CFArrayGetCount(formats)),
1605 (void*)format->format_id);
1606 if (index != kCFNotFound)
1607 CFArrayRemoveValueAtIndex(formats, index);
1608 CFArrayAppendValue(formats, (void*)format->format_id);
1613 CFRelease(types);
1615 TRACE(" -> %s\n", debugstr_cf(formats));
1616 return formats;
1620 /**************************************************************************
1621 * check_clipboard_ownership
1623 static void check_clipboard_ownership(HWND *owner)
1625 CLIPBOARDINFO cbinfo;
1627 if (owner) *owner = NULL;
1629 /* If Wine thinks we're the clipboard owner but Mac OS X thinks we're not
1630 the pasteboard owner, update Wine. */
1631 if (get_clipboard_info(&cbinfo) && (cbinfo.flags & CB_PROCESS))
1633 if (!(cbinfo.flags & CB_OPEN) && !macdrv_is_pasteboard_owner())
1635 TRACE("Lost clipboard ownership\n");
1637 if (OpenClipboard(cbinfo.hwnd_owner))
1639 /* Destroy private objects */
1640 SendMessageW(cbinfo.hwnd_owner, WM_DESTROYCLIPBOARD, 0, 0);
1642 /* Give up ownership of the windows clipboard */
1643 release_ownership();
1644 CloseClipboard();
1647 else if (owner)
1648 *owner = cbinfo.hwnd_owner;
1653 /**************************************************************************
1654 * Mac User Driver Clipboard Exports
1655 **************************************************************************/
1658 /**************************************************************************
1659 * AcquireClipboard (MACDRV.@)
1661 int CDECL macdrv_AcquireClipboard(HWND hwnd)
1663 TRACE("hwnd %p\n", hwnd);
1664 check_clipboard_ownership(NULL);
1665 return 0;
1669 /**************************************************************************
1670 * CountClipboardFormats (MACDRV.@)
1672 INT CDECL macdrv_CountClipboardFormats(void)
1674 CFMutableSetRef seen_formats;
1675 CFArrayRef types;
1676 CFIndex count;
1677 CFIndex i;
1678 INT ret = 0;
1680 TRACE("()\n");
1681 check_clipboard_ownership(NULL);
1683 seen_formats = CFSetCreateMutable(NULL, 0, NULL);
1684 if (!seen_formats)
1686 WARN("Failed to allocate set to track seen formats\n");
1687 return 0;
1690 types = macdrv_copy_pasteboard_types(NULL);
1691 if (!types)
1693 WARN("Failed to copy pasteboard types\n");
1694 CFRelease(seen_formats);
1695 return 0;
1698 count = CFArrayGetCount(types);
1699 TRACE("got %ld types\n", count);
1701 for (i = 0; i < count; i++)
1703 CFStringRef type = CFArrayGetValueAtIndex(types, i);
1704 WINE_CLIPFORMAT* format;
1706 format = NULL;
1707 while ((format = format_for_type(format, type)))
1709 TRACE("for type %s got format %p/%s\n", debugstr_cf(type), format, debugstr_format(format->format_id));
1711 if (!CFSetContainsValue(seen_formats, (void*)format->format_id))
1713 ret++;
1714 CFSetAddValue(seen_formats, (void*)format->format_id);
1719 CFRelease(seen_formats);
1720 TRACE(" -> %d\n", ret);
1721 return ret;
1725 /**************************************************************************
1726 * EmptyClipboard (MACDRV.@)
1728 * Empty cached clipboard data.
1730 void CDECL macdrv_EmptyClipboard(BOOL keepunowned)
1732 TRACE("keepunowned %d\n", keepunowned);
1733 macdrv_clear_pasteboard();
1737 /**************************************************************************
1738 * EndClipboardUpdate (MACDRV.@)
1740 void CDECL macdrv_EndClipboardUpdate(void)
1742 TRACE("()\n");
1743 check_clipboard_ownership(NULL);
1747 /**************************************************************************
1748 * EnumClipboardFormats (MACDRV.@)
1750 UINT CDECL macdrv_EnumClipboardFormats(UINT prev_format)
1752 CFIndex count;
1753 CFIndex i;
1754 UINT ret = 0;
1756 TRACE("prev_format %s\n", debugstr_format(prev_format));
1757 check_clipboard_ownership(NULL);
1759 if (prev_format)
1761 CFArrayRef formats = macdrv_copy_pasteboard_formats(NULL);
1762 if (formats)
1764 count = CFArrayGetCount(formats);
1765 i = CFArrayGetFirstIndexOfValue(formats, CFRangeMake(0, count), (void*)prev_format);
1766 if (i != kCFNotFound && i + 1 < count)
1767 ret = (UINT)CFArrayGetValueAtIndex(formats, i + 1);
1769 CFRelease(formats);
1772 else
1774 CFArrayRef types = macdrv_copy_pasteboard_types(NULL);
1775 if (types)
1777 count = CFArrayGetCount(types);
1778 TRACE("got %ld types\n", count);
1780 if (count)
1782 CFStringRef type = CFArrayGetValueAtIndex(types, 0);
1783 WINE_CLIPFORMAT *format = format_for_type(NULL, type);
1785 ret = format ? format->format_id : 0;
1788 CFRelease(types);
1790 else
1791 WARN("Failed to copy pasteboard types\n");
1794 TRACE(" -> %u\n", ret);
1795 return ret;
1799 /**************************************************************************
1800 * GetClipboardData (MACDRV.@)
1802 HANDLE CDECL macdrv_GetClipboardData(UINT desired_format)
1804 check_clipboard_ownership(NULL);
1806 return macdrv_get_pasteboard_data(NULL, desired_format);
1810 /**************************************************************************
1811 * IsClipboardFormatAvailable (MACDRV.@)
1813 BOOL CDECL macdrv_IsClipboardFormatAvailable(UINT desired_format)
1815 check_clipboard_ownership(NULL);
1816 return macdrv_pasteboard_has_format(NULL, desired_format);
1820 /**************************************************************************
1821 * SetClipboardData (MACDRV.@)
1823 BOOL CDECL macdrv_SetClipboardData(UINT format_id, HANDLE data, BOOL owner)
1825 HWND hwnd_owner;
1826 macdrv_window window;
1827 WINE_CLIPFORMAT *format;
1828 CFDataRef cfdata = NULL;
1830 check_clipboard_ownership(&hwnd_owner);
1831 window = macdrv_get_cocoa_window(GetAncestor(hwnd_owner, GA_ROOT), FALSE);
1832 TRACE("format_id %s data %p owner %d hwnd_owner %p window %p)\n", debugstr_format(format_id), data, owner, hwnd_owner, window);
1834 /* Find the "natural" format for this format_id (the one which isn't
1835 synthesized from another type). */
1836 LIST_FOR_EACH_ENTRY(format, &format_list, WINE_CLIPFORMAT, entry)
1837 if (format->format_id == format_id && !format->synthesized) break;
1839 if (&format->entry == &format_list && !(format = insert_clipboard_format(format_id, NULL)))
1841 WARN("Failed to register clipboard format %s\n", debugstr_format(format_id));
1842 return FALSE;
1845 /* Export the data to the Mac pasteboard. */
1846 if (data)
1848 if (!format->export_func || !(cfdata = format->export_func(data)))
1850 WARN("Failed to export %s data to type %s\n", debugstr_format(format_id), debugstr_cf(format->type));
1851 return FALSE;
1855 if (macdrv_set_pasteboard_data(format->type, cfdata, window))
1856 TRACE("Set pasteboard data for type %s: %s\n", debugstr_cf(format->type), debugstr_cf(cfdata));
1857 else
1859 WARN("Failed to set pasteboard data for type %s: %s\n", debugstr_cf(format->type), debugstr_cf(cfdata));
1860 if (cfdata) CFRelease(cfdata);
1861 return FALSE;
1864 if (cfdata) CFRelease(cfdata);
1866 /* Find any other formats for this format_id (the exportable synthesized ones). */
1867 LIST_FOR_EACH_ENTRY(format, &format_list, WINE_CLIPFORMAT, entry)
1869 if (format->format_id == format_id && format->synthesized && format->export_func)
1871 /* We have a synthesized format for this format ID. Add its type to the pasteboard. */
1872 TRACE("Synthesized from format %s: type %s\n", debugstr_format(format_id), debugstr_cf(format->type));
1874 if (data)
1876 cfdata = format->export_func(data);
1877 if (!cfdata)
1879 WARN("Failed to export %s data to type %s\n", debugstr_format(format->format_id), debugstr_cf(format->type));
1880 continue;
1883 else
1884 cfdata = NULL;
1886 if (macdrv_set_pasteboard_data(format->type, cfdata, window))
1887 TRACE(" ... set pasteboard data: %s\n", debugstr_cf(cfdata));
1888 else
1889 WARN(" ... failed to set pasteboard data: %s\n", debugstr_cf(cfdata));
1891 if (cfdata) CFRelease(cfdata);
1895 if (data)
1897 /* FIXME: According to MSDN, the caller is entitled to lock and read from
1898 data until CloseClipboard is called. So, we should defer this cleanup. */
1899 if ((format_id >= CF_GDIOBJFIRST && format_id <= CF_GDIOBJLAST) ||
1900 format_id == CF_BITMAP ||
1901 format_id == CF_DIB ||
1902 format_id == CF_PALETTE)
1904 DeleteObject(data);
1906 else if (format_id == CF_METAFILEPICT)
1908 DeleteMetaFile(((METAFILEPICT *)GlobalLock(data))->hMF);
1909 GlobalFree(data);
1911 else if (format_id == CF_ENHMETAFILE)
1913 DeleteEnhMetaFile(data);
1915 else if (format_id < CF_PRIVATEFIRST || CF_PRIVATELAST < format_id)
1917 GlobalFree(data);
1921 return TRUE;
1925 /**************************************************************************
1926 * MACDRV Private Clipboard Exports
1927 **************************************************************************/
1930 /**************************************************************************
1931 * macdrv_clipboard_process_attach
1933 void macdrv_clipboard_process_attach(void)
1935 UINT i;
1936 WINE_CLIPFORMAT *format;
1938 /* Register built-in formats */
1939 for (i = 0; i < sizeof(builtin_format_ids)/sizeof(builtin_format_ids[0]); i++)
1941 if (!(format = HeapAlloc(GetProcessHeap(), 0, sizeof(*format)))) break;
1942 format->format_id = builtin_format_ids[i].id;
1943 format->type = CFRetain(builtin_format_ids[i].type);
1944 format->import_func = builtin_format_ids[i].import;
1945 format->export_func = builtin_format_ids[i].export;
1946 format->synthesized = builtin_format_ids[i].synthesized;
1947 list_add_tail(&format_list, &format->entry);
1950 /* Register known mappings between Windows formats and Mac types */
1951 for (i = 0; i < sizeof(builtin_format_names)/sizeof(builtin_format_names[0]); i++)
1953 if (!(format = HeapAlloc(GetProcessHeap(), 0, sizeof(*format)))) break;
1954 format->format_id = RegisterClipboardFormatW(builtin_format_names[i].name);
1955 format->type = CFRetain(builtin_format_names[i].type);
1956 format->import_func = builtin_format_names[i].import;
1957 format->export_func = builtin_format_names[i].export;
1958 format->synthesized = FALSE;
1959 list_add_tail(&format_list, &format->entry);
1964 /**************************************************************************
1965 * query_pasteboard_data
1967 BOOL query_pasteboard_data(HWND hwnd, CFStringRef type)
1969 BOOL ret = FALSE;
1970 CLIPBOARDINFO cbinfo;
1971 WINE_CLIPFORMAT* format;
1972 CFArrayRef types = NULL;
1973 CFRange range;
1975 TRACE("hwnd %p type %s\n", hwnd, debugstr_cf(type));
1977 if (get_clipboard_info(&cbinfo))
1978 hwnd = cbinfo.hwnd_owner;
1980 format = NULL;
1981 while ((format = format_for_type(format, type)))
1983 WINE_CLIPFORMAT* base_format;
1985 TRACE("for type %s got format %p/%s\n", debugstr_cf(type), format, debugstr_format(format->format_id));
1987 if (!format->synthesized)
1989 TRACE("Sending WM_RENDERFORMAT message for format %s to hwnd %p\n", debugstr_format(format->format_id), hwnd);
1990 SendMessageW(hwnd, WM_RENDERFORMAT, format->format_id, 0);
1991 ret = TRUE;
1992 goto done;
1995 if (!types)
1997 types = macdrv_copy_pasteboard_types(NULL);
1998 if (!types)
2000 WARN("Failed to copy pasteboard types\n");
2001 break;
2004 range = CFRangeMake(0, CFArrayGetCount(types));
2007 /* The type maps to a synthesized format. Now look up what type that format maps to natively
2008 (not synthesized). For example, if type is "public.utf8-plain-text", then this format may
2009 have an ID of CF_TEXT. From CF_TEXT, we want to find "org.winehq.builtin.text" to see if
2010 that type is present in the pasteboard. If it is, then the app must have promised it and
2011 we can ask it to render it. (If it had put it on the clipboard immediately, then the
2012 pasteboard would also have data for "public.utf8-plain-text" and we wouldn't be here.) If
2013 "org.winehq.builtin.text" is not on the pasteboard, then one of the other text formats is
2014 presumably responsible for the promise that we're trying to satisfy, so we keep looking. */
2015 LIST_FOR_EACH_ENTRY(base_format, &format_list, WINE_CLIPFORMAT, entry)
2017 if (base_format->format_id == format->format_id && !base_format->synthesized &&
2018 CFArrayContainsValue(types, range, base_format->type))
2020 TRACE("Sending WM_RENDERFORMAT message for format %s to hwnd %p\n", debugstr_format(base_format->format_id), hwnd);
2021 SendMessageW(hwnd, WM_RENDERFORMAT, base_format->format_id, 0);
2022 ret = TRUE;
2023 goto done;
2028 done:
2029 if (types) CFRelease(types);
2031 return ret;