blob: 090bee38d4382fd7f1f94d374ff038d953e735de [file] [log] [blame]
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001/*
Noel Borthwick29700671999-09-03 15:17:57 +00002 * X11 clipboard windows driver
Patrik Stridvalle35d6361998-12-07 09:13:40 +00003 *
4 * Copyright 1994 Martin Ayotte
5 * 1996 Alex Korobka
Noel Borthwick29700671999-09-03 15:17:57 +00006 * 1999 Noel Borthwick
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00007 * 2003 Ulrich Czekalla for CodeWeavers
Noel Borthwick29700671999-09-03 15:17:57 +00008 *
Alexandre Julliard0799c1a2002-03-09 23:29:33 +00009 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 *
Noel Borthwick29700671999-09-03 15:17:57 +000023 * NOTES:
24 * This file contains the X specific implementation for the windows
25 * Clipboard API.
26 *
27 * Wine's internal clipboard is exposed to external apps via the X
28 * selection mechanism.
29 * Currently the driver asserts ownership via two selection atoms:
30 * 1. PRIMARY(XA_PRIMARY)
31 * 2. CLIPBOARD
32 *
Francois Gougetcd8d1812001-05-18 21:01:38 +000033 * In our implementation, the CLIPBOARD selection takes precedence over PRIMARY,
Noel Borthwick29700671999-09-03 15:17:57 +000034 * i.e. if a CLIPBOARD selection is available, it is used instead of PRIMARY.
Francois Gougetcd8d1812001-05-18 21:01:38 +000035 * When Wine takes ownership of the clipboard, it takes ownership of BOTH selections.
Noel Borthwick29700671999-09-03 15:17:57 +000036 * While giving up selection ownership, if the CLIPBOARD selection is lost,
37 * it will lose both PRIMARY and CLIPBOARD and empty the clipboard.
38 * However if only PRIMARY is lost, it will continue to hold the CLIPBOARD selection
39 * (leaving the clipboard cache content unaffected).
40 *
41 * Every format exposed via a windows clipboard format is also exposed through
42 * a corresponding X selection target. A selection target atom is synthesized
43 * whenever a new Windows clipboard format is registered via RegisterClipboardFormat,
Francois Gougetcd8d1812001-05-18 21:01:38 +000044 * or when a built-in format is used for the first time.
Noel Borthwick29700671999-09-03 15:17:57 +000045 * Windows native format are exposed by prefixing the format name with "<WCF>"
46 * This allows us to uniquely identify windows native formats exposed by other
47 * running WINE apps.
48 *
49 * In order to allow external applications to query WINE for supported formats,
50 * we respond to the "TARGETS" selection target. (See EVENT_SelectionRequest
51 * for implementation) We use the same mechanism to query external clients for
Francois Gougetcd8d1812001-05-18 21:01:38 +000052 * availability of a particular format, by caching the list of available targets
Noel Borthwick29700671999-09-03 15:17:57 +000053 * by using the clipboard cache's "delayed render" mechanism. If a selection client
54 * does not support the "TARGETS" selection target, we actually attempt to retrieve
55 * the format requested as a fallback mechanism.
56 *
57 * Certain Windows native formats are automatically converted to X native formats
58 * and vice versa. If a native format is available in the selection, it takes
59 * precedence, in order to avoid unnecessary conversions.
60 *
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +000061 * FIXME: global format list needs a critical section
Patrik Stridvalle35d6361998-12-07 09:13:40 +000062 */
63
François Gouget14259412001-11-06 20:57:11 +000064#include "config.h"
Patrik Stridvalle35d6361998-12-07 09:13:40 +000065
Noel Borthwick29700671999-09-03 15:17:57 +000066#include <string.h>
Alexandre Julliarde37c6e12003-09-05 23:08:26 +000067#include <stdarg.h>
Jeremy Whited3e22d92000-02-10 19:03:02 +000068#include <stdio.h>
Alexandre Julliard908464d2000-11-01 03:11:12 +000069#include <stdlib.h>
Patrik Stridvalld016f812002-08-17 00:43:16 +000070#ifdef HAVE_UNISTD_H
71# include <unistd.h>
72#endif
Juergen Lock7cc0e271999-11-07 05:12:43 +000073#include <fcntl.h>
Ulrich Czekalla651c5982002-08-27 19:19:49 +000074#include <time.h>
Francis Beaudet56ab55d1999-10-24 20:22:24 +000075
François Gouget14259412001-11-06 20:57:11 +000076#include "ts_xlib.h"
Alexandre Julliarde37c6e12003-09-05 23:08:26 +000077#include "windef.h"
78#include "winbase.h"
Dmitry Timoshkovde70d2b2001-06-19 03:32:44 +000079#include "winreg.h"
Patrik Stridvalle35d6361998-12-07 09:13:40 +000080#include "clipboard.h"
Patrik Stridvalle35d6361998-12-07 09:13:40 +000081#include "win.h"
82#include "x11drv.h"
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000083#include "wine/debug.h"
Ulrich Czekallab2df5f92003-06-23 23:02:02 +000084#include "wine/unicode.h"
85#include "wine/server.h"
Patrik Stridvalle35d6361998-12-07 09:13:40 +000086
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000087WINE_DEFAULT_DEBUG_CHANNEL(clipboard);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000088
Ulrich Czekallab2df5f92003-06-23 23:02:02 +000089#define HGDIOBJ_32(handle16) ((HGDIOBJ)(ULONG_PTR)(handle16))
90
Ulrich Czekalla18873e72003-07-08 21:02:51 +000091/* Maximum wait time for selection notify */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +000092#define SELECTION_RETRIES 500 /* wait for .1 seconds */
93#define SELECTION_WAIT 1000 /* us */
Ulrich Czekalla18873e72003-07-08 21:02:51 +000094/* Minimum seconds that must lapse between owner queries */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +000095#define OWNERQUERYLAPSETIME 1
Ulrich Czekalla651c5982002-08-27 19:19:49 +000096
Noel Borthwick29700671999-09-03 15:17:57 +000097/* Selection masks */
Noel Borthwick29700671999-09-03 15:17:57 +000098#define S_NOSELECTION 0
99#define S_PRIMARY 1
100#define S_CLIPBOARD 2
101
Francis Beaudet56ab55d1999-10-24 20:22:24 +0000102static int selectionAcquired = 0; /* Contains the current selection masks */
Noel Borthwick29700671999-09-03 15:17:57 +0000103static Window selectionWindow = None; /* The top level X window which owns the selection */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000104static BOOL clearAllSelections = FALSE; /* Always lose all selections */
105static Atom selectionCacheSrc = XA_PRIMARY; /* The selection source from which the clipboard cache was filled */
Noel Borthwick29700671999-09-03 15:17:57 +0000106static Window PrimarySelectionOwner = None; /* The window which owns the primary selection */
107static Window ClipboardSelectionOwner = None; /* The window which owns the clipboard selection */
Noel Borthwick29700671999-09-03 15:17:57 +0000108
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000109INT X11DRV_RegisterClipboardFormat(LPCSTR FormatName);
110void X11DRV_EmptyClipboard(void);
111void X11DRV_EndClipboardUpdate(void);
112HANDLE X11DRV_CLIPBOARD_ImportClipboardData(LPBYTE lpdata, UINT cBytes);
113HANDLE X11DRV_CLIPBOARD_ImportEnhMetaFile(LPBYTE lpdata, UINT cBytes);
114HANDLE X11DRV_CLIPBOARD_ImportMetaFilePict(LPBYTE lpdata, UINT cBytes);
115HANDLE X11DRV_CLIPBOARD_ImportXAPIXMAP(LPBYTE lpdata, UINT cBytes);
116HANDLE X11DRV_CLIPBOARD_ImportXAString(LPBYTE lpdata, UINT cBytes);
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000117HANDLE X11DRV_CLIPBOARD_ExportClipboardData(Window requestor, Atom aTarget,
118 Atom rprop, LPWINE_CLIPDATA lpData, LPDWORD lpBytes);
119HANDLE X11DRV_CLIPBOARD_ExportString(Window requestor, Atom aTarget,
120 Atom rprop, LPWINE_CLIPDATA lpData, LPDWORD lpBytes);
121HANDLE X11DRV_CLIPBOARD_ExportXAPIXMAP(Window requestor, Atom aTarget,
122 Atom rprop, LPWINE_CLIPDATA lpdata, LPDWORD lpBytes);
123HANDLE X11DRV_CLIPBOARD_ExportMetaFilePict(Window requestor, Atom aTarget,
124 Atom rprop, LPWINE_CLIPDATA lpdata, LPDWORD lpBytes);
125HANDLE X11DRV_CLIPBOARD_ExportEnhMetaFile(Window requestor, Atom aTarget,
126 Atom rprop, LPWINE_CLIPDATA lpdata, LPDWORD lpBytes);
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +0000127static WINE_CLIPFORMAT *X11DRV_CLIPBOARD_InsertClipboardFormat(LPCSTR FormatName, Atom prop);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000128static BOOL X11DRV_CLIPBOARD_ReadSelection(LPWINE_CLIPFORMAT lpData, Window w, Atom prop);
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000129static BOOL X11DRV_CLIPBOARD_RenderSynthesizedText(UINT wFormatID);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000130static void X11DRV_CLIPBOARD_FreeData(LPWINE_CLIPDATA lpData);
131static BOOL X11DRV_CLIPBOARD_IsSelectionOwner(void);
132static int X11DRV_CLIPBOARD_QueryAvailableData(LPCLIPBOARDINFO lpcbinfo);
133static BOOL X11DRV_CLIPBOARD_ReadClipboardData(UINT wFormat);
134static BOOL X11DRV_CLIPBOARD_RenderFormat(LPWINE_CLIPDATA lpData);
135static HANDLE X11DRV_CLIPBOARD_SerializeMetafile(INT wformat, HANDLE hdata, LPDWORD lpcbytes, BOOL out);
136static BOOL X11DRV_CLIPBOARD_SynthesizeData(UINT wFormatID);
137static BOOL X11DRV_CLIPBOARD_RenderSynthesizedFormat(LPWINE_CLIPDATA lpData);
138
139/* Clipboard formats
140 * WARNING: This data ordering is dependent on the WINE_CLIPFORMAT structure
141 * declared in clipboard.h
142 */
Alexandre Julliardd09c3282003-11-20 04:24:18 +0000143static WINE_CLIPFORMAT ClipFormats[] =
Alexandre Julliard96ebf152000-01-26 02:21:30 +0000144{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000145 { CF_TEXT, "WCF_TEXT", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
146 X11DRV_CLIPBOARD_ExportClipboardData, NULL, &ClipFormats[1]},
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000147
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000148 { CF_BITMAP, "WCF_BITMAP", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
149 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[0], &ClipFormats[2]},
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000150
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000151 { CF_METAFILEPICT, "WCF_METAFILEPICT", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportMetaFilePict,
152 X11DRV_CLIPBOARD_ExportMetaFilePict, &ClipFormats[1], &ClipFormats[3]},
153
154 { CF_SYLK, "WCF_SYLK", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
155 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[2], &ClipFormats[4]},
156
157 { CF_DIF, "WCF_DIF", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
158 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[3], &ClipFormats[5]},
159
160 { CF_TIFF, "WCF_TIFF", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
161 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[4], &ClipFormats[6]},
162
163 { CF_OEMTEXT, "WCF_OEMTEXT", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
164 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[5], &ClipFormats[7]},
165
166 { CF_DIB, "WCF_DIB", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportXAPIXMAP,
167 X11DRV_CLIPBOARD_ExportXAPIXMAP, &ClipFormats[6], &ClipFormats[8]},
168
169 { CF_PALETTE, "WCF_PALETTE", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
170 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[7], &ClipFormats[9]},
171
172 { CF_PENDATA, "WCF_PENDATA", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
173 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[8], &ClipFormats[10]},
174
175 { CF_RIFF, "WCF_RIFF", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
176 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[9], &ClipFormats[11]},
177
178 { CF_WAVE, "WCF_WAVE", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
179 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[10], &ClipFormats[12]},
180
181 { CF_UNICODETEXT, "WCF_UNICODETEXT", XA_STRING, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportXAString,
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000182 X11DRV_CLIPBOARD_ExportString, &ClipFormats[11], &ClipFormats[13]},
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000183
184 { CF_ENHMETAFILE, "WCF_ENHMETAFILE", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportEnhMetaFile,
185 X11DRV_CLIPBOARD_ExportEnhMetaFile, &ClipFormats[12], &ClipFormats[14]},
186
187 { CF_HDROP, "WCF_HDROP", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
188 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[13], &ClipFormats[15]},
189
190 { CF_LOCALE, "WCF_LOCALE", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
191 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[14], &ClipFormats[16]},
192
193 { CF_DIBV5, "WCF_DIBV5", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
194 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[15], &ClipFormats[17]},
195
196 { CF_OWNERDISPLAY, "WCF_OWNERDISPLAY", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
197 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[16], &ClipFormats[18]},
198
199 { CF_DSPTEXT, "WCF_DSPTEXT", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
200 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[17], &ClipFormats[19]},
201
202 { CF_DSPBITMAP, "WCF_DSPBITMAP", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
203 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[18], &ClipFormats[20]},
204
205 { CF_DSPMETAFILEPICT, "WCF_DSPMETAFILEPICT", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
206 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[19], &ClipFormats[21]},
207
208 { CF_DSPENHMETAFILE, "WCF_DSPENHMETAFILE", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
209 X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[20], NULL}
210};
211
Alexandre Julliardd09c3282003-11-20 04:24:18 +0000212#define GET_ATOM(prop) (((prop) < FIRST_XATOM) ? (Atom)(prop) : X11DRV_Atoms[(prop) - FIRST_XATOM])
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000213
214/* Maps X properties to Windows formats */
Alexandre Julliardd09c3282003-11-20 04:24:18 +0000215static const struct
216{
217 LPCSTR lpszFormat;
218 UINT prop;
219} PropertyFormatMap[] =
220{
221 { "Rich Text Format", XATOM_text_rtf },
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000222 /* Temporarily disable text/html because Evolution incorrectly pastes strings with extra nulls */
223 /*{ "text/html", "HTML Format" },*/
Alexandre Julliardd09c3282003-11-20 04:24:18 +0000224 { "GIF", XATOM_image_gif }
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000225};
226
227
228/* Maps equivalent X properties. It is assumed that lpszProperty must already
229 be in ClipFormats or PropertyFormatMap. */
Alexandre Julliardd09c3282003-11-20 04:24:18 +0000230static const struct
231{
232 UINT drvDataProperty;
233 UINT drvDataAlias;
234} PropertyAliasMap[] =
235{
236 /* DataProperty, DataAlias */
237 { XATOM_text_rtf, XATOM_text_richtext },
238 { XA_STRING, XATOM_COMPOUND_TEXT },
239 { XA_STRING, XATOM_TEXT },
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000240};
241
242
243/*
244 * Cached clipboard data.
245 */
246static LPWINE_CLIPDATA ClipData = NULL;
247static UINT ClipDataCount = 0;
248
249/*
250 * Clipboard sequence number
251 */
Alexandre Julliardd09c3282003-11-20 04:24:18 +0000252static UINT wSeqNo = 0;
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000253
254/**************************************************************************
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000255 * Internal Clipboard implementation methods
256 **************************************************************************/
Noel Borthwick29700671999-09-03 15:17:57 +0000257
258/**************************************************************************
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000259 * X11DRV_InitClipboard
Noel Borthwick29700671999-09-03 15:17:57 +0000260 */
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +0000261void X11DRV_InitClipboard(void)
Noel Borthwick29700671999-09-03 15:17:57 +0000262{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000263 INT i;
Dmitry Timoshkovde70d2b2001-06-19 03:32:44 +0000264 HKEY hkey;
Francis Beaudet56ab55d1999-10-24 20:22:24 +0000265
Dmitry Timoshkovde70d2b2001-06-19 03:32:44 +0000266 if(!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\Clipboard", &hkey))
267 {
268 char buffer[20];
269 DWORD type, count = sizeof(buffer);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000270 if(!RegQueryValueExA(hkey, "ClearAllSelections", 0, &type, buffer, &count))
271 clearAllSelections = atoi(buffer);
272 RegCloseKey(hkey);
Dmitry Timoshkovde70d2b2001-06-19 03:32:44 +0000273 }
Alexandre Julliard43230042001-05-16 19:52:29 +0000274
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000275 /* Register known mapping between window formats and X properties */
Alexandre Julliardd09c3282003-11-20 04:24:18 +0000276 for (i = 0; i < sizeof(PropertyFormatMap)/sizeof(PropertyFormatMap[0]); i++)
277 X11DRV_CLIPBOARD_InsertClipboardFormat(PropertyFormatMap[i].lpszFormat,
278 GET_ATOM(PropertyFormatMap[i].prop));
Francis Beaudet56ab55d1999-10-24 20:22:24 +0000279}
280
281
282/**************************************************************************
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +0000283 * intern_atoms
284 *
285 * Intern atoms for formats that don't have one yet.
286 */
287static void intern_atoms(void)
288{
289 LPWINE_CLIPFORMAT format;
290 int i, count;
291 char **names;
292 Atom *atoms;
293
294 for (format = ClipFormats, count = 0; format; format = format->NextFormat)
295 if (!format->drvData) count++;
296 if (!count) return;
297
298 names = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*names) );
299 atoms = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*atoms) );
300
301 for (format = ClipFormats, i = 0; format; format = format->NextFormat)
302 if (!format->drvData) names[i++] = format->Name;
303
304 wine_tsx11_lock();
305 XInternAtoms( thread_display(), names, count, False, atoms );
306 wine_tsx11_unlock();
307
308 for (format = ClipFormats, i = 0; format; format = format->NextFormat)
309 if (!format->drvData) format->drvData = atoms[i];
310
311 HeapFree( GetProcessHeap(), 0, names );
312 HeapFree( GetProcessHeap(), 0, atoms );
313}
314
315
316/**************************************************************************
317 * register_format
318 *
319 * Register a custom X clipboard format.
320 */
321static WINE_CLIPFORMAT *register_format( LPCSTR FormatName, Atom prop )
322{
323 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
324
325 TRACE("'%s'\n", FormatName);
326
327 /* walk format chain to see if it's already registered */
328 while (lpFormat)
329 {
330 if ( !strcasecmp(lpFormat->Name, FormatName) &&
331 (lpFormat->wFlags & CF_FLAG_BUILTINFMT) == 0)
332 return lpFormat;
333 lpFormat = lpFormat->NextFormat;
334 }
335
336 return X11DRV_CLIPBOARD_InsertClipboardFormat(FormatName, prop);
337}
338
339
340/**************************************************************************
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000341 * X11DRV_CLIPBOARD_LookupFormat
342 */
343LPWINE_CLIPFORMAT X11DRV_CLIPBOARD_LookupFormat(WORD wID)
344{
345 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
346
347 while(lpFormat)
348 {
349 if (lpFormat->wFormatID == wID)
350 break;
351
352 lpFormat = lpFormat->NextFormat;
353 }
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +0000354 if (!lpFormat->drvData) intern_atoms();
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000355 return lpFormat;
356}
357
358
359/**************************************************************************
360 * X11DRV_CLIPBOARD_LookupProperty
361 */
362LPWINE_CLIPFORMAT X11DRV_CLIPBOARD_LookupProperty(UINT drvData)
363{
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +0000364 for (;;)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000365 {
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +0000366 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
367 BOOL need_intern = FALSE;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000368
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +0000369 while(lpFormat)
370 {
371 if (lpFormat->drvData == drvData) return lpFormat;
372 if (!lpFormat->drvData) need_intern = TRUE;
373 lpFormat = lpFormat->NextFormat;
374 }
375 if (!need_intern) return NULL;
376 intern_atoms();
377 /* restart the search for the new atoms */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000378 }
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000379}
380
381
382/**************************************************************************
383 * X11DRV_CLIPBOARD_LookupAliasProperty
384 */
385LPWINE_CLIPFORMAT X11DRV_CLIPBOARD_LookupAliasProperty(UINT drvDataAlias)
386{
387 unsigned int i;
388 LPWINE_CLIPFORMAT lpFormat = NULL;
389
Alexandre Julliardd09c3282003-11-20 04:24:18 +0000390 for (i = 0; i < sizeof(PropertyAliasMap)/sizeof(PropertyAliasMap[0]); i++)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000391 {
Alexandre Julliardd09c3282003-11-20 04:24:18 +0000392 if (GET_ATOM(PropertyAliasMap[i].drvDataAlias) == drvDataAlias)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000393 {
Alexandre Julliardd09c3282003-11-20 04:24:18 +0000394 lpFormat = X11DRV_CLIPBOARD_LookupProperty(GET_ATOM(PropertyAliasMap[i].drvDataProperty));
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000395 break;
396 }
397 }
398
399 return lpFormat;
400}
401
402
403/**************************************************************************
404 * X11DRV_CLIPBOARD_LookupPropertyAlias
405 */
406UINT X11DRV_CLIPBOARD_LookupPropertyAlias(UINT drvDataProperty)
407{
408 unsigned int i;
409 UINT alias = 0;
410
Alexandre Julliardd09c3282003-11-20 04:24:18 +0000411 for (i = 0; i < sizeof(PropertyAliasMap)/sizeof(PropertyAliasMap[0]); i++)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000412 {
Alexandre Julliardd09c3282003-11-20 04:24:18 +0000413 if (GET_ATOM(PropertyAliasMap[i].drvDataProperty) == drvDataProperty)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000414 {
Alexandre Julliardd09c3282003-11-20 04:24:18 +0000415 alias = GET_ATOM(PropertyAliasMap[i].drvDataAlias);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000416 break;
417 }
418 }
419
420 return alias;
421}
422
423
424/**************************************************************************
425 * X11DRV_CLIPBOARD_LookupData
426 */
427LPWINE_CLIPDATA X11DRV_CLIPBOARD_LookupData(DWORD wID)
428{
429 LPWINE_CLIPDATA lpData = ClipData;
430
431 if (lpData)
432 {
433 do
434 {
435 if (lpData->wFormatID == wID)
436 break;
437
438 lpData = lpData->NextData;
439 }
440 while(lpData != ClipData);
441
442 if (lpData->wFormatID != wID)
443 lpData = NULL;
444 }
445
446 return lpData;
447}
448
449
450/**************************************************************************
451 * InsertClipboardFormat
452 */
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +0000453static WINE_CLIPFORMAT *X11DRV_CLIPBOARD_InsertClipboardFormat(LPCSTR FormatName, Atom prop)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000454{
455 LPWINE_CLIPFORMAT lpFormat;
456 LPWINE_CLIPFORMAT lpNewFormat;
457
458 /* allocate storage for new format entry */
459 lpNewFormat = (LPWINE_CLIPFORMAT) HeapAlloc(GetProcessHeap(),
460 0, sizeof(WINE_CLIPFORMAT));
461
462 if(lpNewFormat == NULL)
463 {
464 WARN("No more memory for a new format!\n");
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +0000465 return NULL;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000466 }
467
468 if (!(lpNewFormat->Name = HeapAlloc(GetProcessHeap(), 0, strlen(FormatName)+1)))
469 {
470 WARN("No more memory for the new format name!\n");
471 HeapFree(GetProcessHeap(), 0, lpNewFormat);
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +0000472 return NULL;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000473 }
474
475 strcpy(lpNewFormat->Name, FormatName);
476 lpNewFormat->wFlags = 0;
477 lpNewFormat->wFormatID = GlobalAddAtomA(lpNewFormat->Name);
Alexandre Julliardd09c3282003-11-20 04:24:18 +0000478 lpNewFormat->drvData = prop;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000479 lpNewFormat->lpDrvImportFunc = X11DRV_CLIPBOARD_ImportClipboardData;
480 lpNewFormat->lpDrvExportFunc = X11DRV_CLIPBOARD_ExportClipboardData;
481
482 /* Link Format */
483 lpFormat = ClipFormats;
484
485 while(lpFormat->NextFormat) /* Move to last entry */
486 lpFormat = lpFormat->NextFormat;
487
488 lpNewFormat->NextFormat = NULL;
489 lpFormat->NextFormat = lpNewFormat;
490 lpNewFormat->PrevFormat = lpFormat;
491
Alexandre Julliardd09c3282003-11-20 04:24:18 +0000492 TRACE("Registering format(%d): %s drvData %d\n",
493 lpNewFormat->wFormatID, FormatName, lpNewFormat->drvData);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000494
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +0000495 return lpNewFormat;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000496}
497
498
499
500
501/**************************************************************************
502 * X11DRV_CLIPBOARD_GetClipboardInfo
503 */
504static BOOL X11DRV_CLIPBOARD_GetClipboardInfo(LPCLIPBOARDINFO cbInfo)
505{
506 BOOL bRet = FALSE;
507
508 SERVER_START_REQ( set_clipboard_info )
509 {
510 req->flags = 0;
511
512 if (wine_server_call_err( req ))
513 {
514 ERR("Failed to get clipboard owner.\n");
515 }
516 else
517 {
518 cbInfo->hWndOpen = reply->old_clipboard;
519 cbInfo->hWndOwner = reply->old_owner;
520 cbInfo->hWndViewer = reply->old_viewer;
521 cbInfo->seqno = reply->seqno;
522 cbInfo->flags = reply->flags;
523
524 bRet = TRUE;
525 }
526 }
527 SERVER_END_REQ;
528
529 return bRet;
530}
531
532
533/**************************************************************************
534 * X11DRV_CLIPBOARD_ReleaseOwnership
535 */
536static BOOL X11DRV_CLIPBOARD_ReleaseOwnership(void)
537{
538 BOOL bRet = FALSE;
539
540 SERVER_START_REQ( set_clipboard_info )
541 {
542 req->flags = SET_CB_RELOWNER | SET_CB_SEQNO;
543
544 if (wine_server_call_err( req ))
545 {
546 ERR("Failed to set clipboard.\n");
547 }
548 else
549 {
550 bRet = TRUE;
551 }
552 }
553 SERVER_END_REQ;
554
555 return bRet;
556}
557
558
559
560/**************************************************************************
561 * X11DRV_CLIPBOARD_InsertClipboardData
562 *
563 * Caller *must* have the clipboard open and be the owner.
564 */
565static BOOL X11DRV_CLIPBOARD_InsertClipboardData(UINT wFormat, HANDLE16 hData16, HANDLE hData32, DWORD flags)
566{
567 LPWINE_CLIPDATA lpData = X11DRV_CLIPBOARD_LookupData(wFormat);
568
569 TRACE("format=%d lpData=%p hData16=%08x hData32=%08x flags=0x%08lx\n",
570 wFormat, lpData, hData16, (unsigned int)hData32, flags);
571
572 if (lpData)
573 {
574 X11DRV_CLIPBOARD_FreeData(lpData);
575
576 lpData->hData16 = hData16; /* 0 is legal, see WM_RENDERFORMAT */
577 lpData->hData32 = hData32;
578 }
579 else
580 {
581 lpData = (LPWINE_CLIPDATA) HeapAlloc(GetProcessHeap(),
582 0, sizeof(WINE_CLIPDATA));
583
584 lpData->wFormatID = wFormat;
585 lpData->hData16 = hData16; /* 0 is legal, see WM_RENDERFORMAT */
586 lpData->hData32 = hData32;
587
588 if (ClipData)
589 {
590 LPWINE_CLIPDATA lpPrevData = ClipData->PrevData;
591
592 lpData->PrevData = lpPrevData;
593 lpData->NextData = ClipData;
594
595 lpPrevData->NextData = lpData;
596 ClipData->PrevData = lpData;
597 }
598 else
599 {
600 lpData->NextData = lpData;
601 lpData->PrevData = lpData;
602 ClipData = lpData;
603 }
604
605 ClipDataCount++;
606 }
607
608 lpData->wFlags = flags;
609
610 return TRUE;
611}
612
613
614/**************************************************************************
615 * X11DRV_CLIPBOARD_FreeData
616 *
617 * Free clipboard data handle.
618 */
619static void X11DRV_CLIPBOARD_FreeData(LPWINE_CLIPDATA lpData)
620{
621 TRACE("%d\n", lpData->wFormatID);
622
623 if ((lpData->wFormatID >= CF_GDIOBJFIRST &&
624 lpData->wFormatID <= CF_GDIOBJLAST) ||
625 lpData->wFormatID == CF_BITMAP ||
626 lpData->wFormatID == CF_DIB ||
627 lpData->wFormatID == CF_PALETTE)
628 {
629 if (lpData->hData32)
630 DeleteObject(lpData->hData32);
631
632 if (lpData->hData16)
633 DeleteObject(HGDIOBJ_32(lpData->hData16));
634 }
635 else if (lpData->wFormatID == CF_METAFILEPICT)
636 {
637 if (lpData->hData32)
638 {
639 DeleteMetaFile(((METAFILEPICT *)GlobalLock( lpData->hData32 ))->hMF );
640 GlobalFree(lpData->hData32);
641
642 if (lpData->hData16)
643 /* HMETAFILE16 and HMETAFILE32 are apparently the same thing,
644 and a shallow copy is enough to share a METAFILEPICT
645 structure between 16bit and 32bit clipboards. The MetaFile
646 should of course only be deleted once. */
647 GlobalFree16(lpData->hData16);
648 }
649
650 if (lpData->hData16)
651 {
652 METAFILEPICT16* lpMetaPict = (METAFILEPICT16 *) GlobalLock16(lpData->hData16);
653
654 if (lpMetaPict)
655 {
656 DeleteMetaFile16(lpMetaPict->hMF);
657 lpMetaPict->hMF = 0;
658 }
659
660 GlobalFree16(lpData->hData16);
661 }
662 }
663 else if (lpData->wFormatID == CF_ENHMETAFILE)
664 {
665 if (lpData->hData32)
666 DeleteEnhMetaFile(lpData->hData32);
667 }
668 else if (lpData->wFormatID < CF_PRIVATEFIRST ||
669 lpData->wFormatID > CF_PRIVATELAST)
670 {
671 if (lpData->hData32)
672 GlobalFree(lpData->hData32);
673
674 if (lpData->hData16)
675 GlobalFree16(lpData->hData16);
676 }
677
678 lpData->hData16 = 0;
679 lpData->hData32 = 0;
680}
681
682
683/**************************************************************************
684 * X11DRV_CLIPBOARD_UpdateCache
685 */
686static BOOL X11DRV_CLIPBOARD_UpdateCache(LPCLIPBOARDINFO lpcbinfo)
687{
688 BOOL bret = TRUE;
689
690 if (!X11DRV_CLIPBOARD_IsSelectionOwner())
691 {
692 if (!X11DRV_CLIPBOARD_GetClipboardInfo(lpcbinfo))
693 {
694 ERR("Failed to retrieve clipboard information.\n");
695 bret = FALSE;
696 }
697 else if (wSeqNo < lpcbinfo->seqno)
698 {
699 X11DRV_EmptyClipboard();
700
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000701 if (X11DRV_CLIPBOARD_QueryAvailableData(lpcbinfo) < 0)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000702 {
703 ERR("Failed to cache clipboard data owned by another process.\n");
704 bret = FALSE;
705 }
706 else
707 {
708 X11DRV_EndClipboardUpdate();
709 }
710
711 wSeqNo = lpcbinfo->seqno;
712 }
713 }
714
715 return bret;
716}
717
718
719/**************************************************************************
720 * X11DRV_CLIPBOARD_RenderFormat
721 */
722static BOOL X11DRV_CLIPBOARD_RenderFormat(LPWINE_CLIPDATA lpData)
723{
724 BOOL bret = TRUE;
725
726 TRACE(" 0x%04x hData32(0x%08x) hData16(0x%08x)\n",
727 lpData->wFormatID, (unsigned int)lpData->hData32, lpData->hData16);
728
729 if (lpData->hData32 || lpData->hData16)
730 return bret; /* Already rendered */
731
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000732 if (lpData->wFlags & CF_FLAG_SYNTHESIZED)
733 bret = X11DRV_CLIPBOARD_RenderSynthesizedFormat(lpData);
734 else if (!X11DRV_CLIPBOARD_IsSelectionOwner())
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000735 {
736 if (!X11DRV_CLIPBOARD_ReadClipboardData(lpData->wFormatID))
737 {
738 ERR("Failed to cache clipboard data owned by another process. Format=%d\n",
739 lpData->wFormatID);
740 bret = FALSE;
741 }
742 }
743 else
744 {
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000745 CLIPBOARDINFO cbInfo;
746
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000747 if (X11DRV_CLIPBOARD_GetClipboardInfo(&cbInfo) && cbInfo.hWndOwner)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000748 {
749 /* Send a WM_RENDERFORMAT message to notify the owner to render the
750 * data requested into the clipboard.
751 */
752 TRACE("Sending WM_RENDERFORMAT message to hwnd(%p)\n", cbInfo.hWndOwner);
753 SendMessageW(cbInfo.hWndOwner, WM_RENDERFORMAT, (WPARAM)lpData->wFormatID, 0);
754
755 if (!lpData->hData32 && !lpData->hData16)
756 bret = FALSE;
757 }
758 else
759 {
760 ERR("hWndClipOwner is lost!\n");
761 bret = FALSE;
762 }
763 }
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000764
765 return bret;
766}
767
768
769/**************************************************************************
770 * CLIPBOARD_ConvertText
771 * Returns number of required/converted characters - not bytes!
772 */
773static INT CLIPBOARD_ConvertText(WORD src_fmt, void const *src, INT src_size,
774 WORD dst_fmt, void *dst, INT dst_size)
775{
776 UINT cp;
777
778 if(src_fmt == CF_UNICODETEXT)
779 {
780 switch(dst_fmt)
781 {
782 case CF_TEXT:
783 cp = CP_ACP;
784 break;
785 case CF_OEMTEXT:
786 cp = CP_OEMCP;
787 break;
788 default:
789 return 0;
790 }
791 return WideCharToMultiByte(cp, 0, src, src_size, dst, dst_size, NULL, NULL);
792 }
793
794 if(dst_fmt == CF_UNICODETEXT)
795 {
796 switch(src_fmt)
797 {
798 case CF_TEXT:
799 cp = CP_ACP;
800 break;
801 case CF_OEMTEXT:
802 cp = CP_OEMCP;
803 break;
804 default:
805 return 0;
806 }
807 return MultiByteToWideChar(cp, 0, src, src_size, dst, dst_size);
808 }
809
810 if(!dst_size) return src_size;
811
812 if(dst_size > src_size) dst_size = src_size;
813
814 if(src_fmt == CF_TEXT )
815 CharToOemBuffA(src, dst, dst_size);
816 else
817 OemToCharBuffA(src, dst, dst_size);
818
819 return dst_size;
820}
821
822
823/**************************************************************************
824 * X11DRV_CLIPBOARD_RenderSynthesizedFormat
825 */
826static BOOL X11DRV_CLIPBOARD_RenderSynthesizedFormat(LPWINE_CLIPDATA lpData)
827{
828 BOOL bret = FALSE;
829
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000830 TRACE("\n");
831
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000832 if (lpData->wFlags & CF_FLAG_SYNTHESIZED)
833 {
834 UINT wFormatID = lpData->wFormatID;
835
836 if (wFormatID == CF_UNICODETEXT || wFormatID == CF_TEXT || wFormatID == CF_OEMTEXT)
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000837 bret = X11DRV_CLIPBOARD_RenderSynthesizedText(wFormatID);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000838 else
839 {
840 switch (wFormatID)
841 {
842 case CF_ENHMETAFILE:
843 case CF_METAFILEPICT:
844 case CF_DIB:
845 case CF_BITMAP:
846 FIXME("Synthesizing wFormatID(0x%08x) not implemented\n", wFormatID);
847 break;
848
849 default:
850 FIXME("Called to synthesize unknown format\n");
851 break;
852 }
853 }
854
855 lpData->wFlags &= ~CF_FLAG_SYNTHESIZED;
856 }
857
858 return bret;
859}
860
861
862/**************************************************************************
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000863 * X11DRV_CLIPBOARD_RenderSynthesizedText
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000864 *
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000865 * Renders synthesized text
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000866 */
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000867static BOOL X11DRV_CLIPBOARD_RenderSynthesizedText(UINT wFormatID)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000868{
869 LPCSTR lpstrS;
870 LPSTR lpstrT;
871 HANDLE hData32;
872 INT src_chars, dst_chars, alloc_size;
873 LPWINE_CLIPDATA lpSource = NULL;
874
875 TRACE(" %d\n", wFormatID);
876
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000877 if ((lpSource = X11DRV_CLIPBOARD_LookupData(wFormatID)) &&
878 lpSource->hData32)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000879 return TRUE;
880
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000881 /* Look for rendered source or non-synthesized source */
882 if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_UNICODETEXT)) &&
883 (!(lpSource->wFlags & CF_FLAG_SYNTHESIZED) || lpSource->hData32))
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000884 {
885 TRACE("UNICODETEXT -> %d\n", wFormatID);
886 }
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000887 else if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_TEXT)) &&
888 (!(lpSource->wFlags & CF_FLAG_SYNTHESIZED) || lpSource->hData32))
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000889 {
890 TRACE("TEXT -> %d\n", wFormatID);
891 }
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000892 else if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_OEMTEXT)) &&
893 (!(lpSource->wFlags & CF_FLAG_SYNTHESIZED) || lpSource->hData32))
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000894 {
895 TRACE("OEMTEXT -> %d\n", wFormatID);
896 }
897
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000898 if (!lpSource || (lpSource->wFlags & CF_FLAG_SYNTHESIZED &&
899 !lpSource->hData32))
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000900 return FALSE;
901
Ulrich Czekalla18873e72003-07-08 21:02:51 +0000902 /* Ask the clipboard owner to render the source text if necessary */
903 if (!lpSource->hData32 && !X11DRV_CLIPBOARD_RenderFormat(lpSource))
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000904 return FALSE;
905
906 if (lpSource->hData32)
907 {
908 lpstrS = (LPSTR)GlobalLock(lpSource->hData32);
909 }
910 else
911 {
912 lpstrS = (LPSTR)GlobalLock16(lpSource->hData16);
913 }
914
915 if (!lpstrS)
916 return FALSE;
917
918 /* Text always NULL terminated */
919 if(lpSource->wFormatID == CF_UNICODETEXT)
920 src_chars = strlenW((LPCWSTR)lpstrS) + 1;
921 else
922 src_chars = strlen(lpstrS) + 1;
923
924 /* Calculate number of characters in the destination buffer */
925 dst_chars = CLIPBOARD_ConvertText(lpSource->wFormatID, lpstrS,
926 src_chars, wFormatID, NULL, 0);
927
928 if (!dst_chars)
929 return FALSE;
930
931 TRACE("Converting from '%d' to '%d', %i chars\n",
932 lpSource->wFormatID, wFormatID, src_chars);
933
934 /* Convert characters to bytes */
935 if(wFormatID == CF_UNICODETEXT)
936 alloc_size = dst_chars * sizeof(WCHAR);
937 else
938 alloc_size = dst_chars;
939
940 hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE |
941 GMEM_DDESHARE, alloc_size);
942
943 lpstrT = (LPSTR)GlobalLock(hData32);
944
945 if (lpstrT)
946 {
947 CLIPBOARD_ConvertText(lpSource->wFormatID, lpstrS, src_chars,
948 wFormatID, lpstrT, dst_chars);
949 GlobalUnlock(hData32);
950 }
951
952 /* Unlock source */
953 if (lpSource->hData32)
954 GlobalUnlock(lpSource->hData32);
955 else
956 GlobalUnlock16(lpSource->hData16);
957
958 return X11DRV_CLIPBOARD_InsertClipboardData(wFormatID, 0, hData32, 0);
959}
960
961
962/**************************************************************************
963 * X11DRV_CLIPBOARD_ImportXAString
964 *
965 * Import XA_STRING, converting the string to CF_UNICODE.
966 */
967HANDLE X11DRV_CLIPBOARD_ImportXAString(LPBYTE lpdata, UINT cBytes)
968{
969 LPSTR lpstr;
970 UINT i, inlcount = 0;
971 HANDLE hUnicodeText = 0;
972
973 for (i = 0; i <= cBytes; i++)
974 {
975 if (lpdata[i] == '\n')
976 inlcount++;
977 }
978
979 if ((lpstr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cBytes + inlcount + 1)))
980 {
981 UINT count;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000982
983 for (i = 0, inlcount = 0; i <= cBytes; i++)
984 {
985 if (lpdata[i] == '\n')
986 lpstr[inlcount++] = '\r';
987
988 lpstr[inlcount++] = lpdata[i];
989 }
990
Dmitry Timoshkov8a8d1b92003-07-09 04:22:57 +0000991 count = MultiByteToWideChar(CP_UNIXCP, 0, lpstr, -1, NULL, 0);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000992 hUnicodeText = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, count * sizeof(WCHAR));
993
994 if(hUnicodeText)
995 {
996 WCHAR *textW = GlobalLock(hUnicodeText);
Dmitry Timoshkov8a8d1b92003-07-09 04:22:57 +0000997 MultiByteToWideChar(CP_UNIXCP, 0, lpstr, -1, textW, count);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000998 GlobalUnlock(hUnicodeText);
999 }
1000
1001 HeapFree(GetProcessHeap(), 0, lpstr);
1002 }
1003
1004 return hUnicodeText;
1005}
1006
1007
1008/**************************************************************************
1009 * X11DRV_CLIPBOARD_ImportXAPIXMAP
1010 *
1011 * Import XA_PIXMAP, converting the image to CF_DIB.
1012 */
1013HANDLE X11DRV_CLIPBOARD_ImportXAPIXMAP(LPBYTE lpdata, UINT cBytes)
1014{
1015 HANDLE hTargetImage = 0; /* Handle to store the converted DIB */
1016 Pixmap *pPixmap = (Pixmap *) lpdata;
1017 HWND hwnd = GetOpenClipboardWindow();
1018 HDC hdc = GetDC(hwnd);
1019
1020 hTargetImage = X11DRV_DIB_CreateDIBFromPixmap(*pPixmap, hdc, TRUE);
1021
1022 ReleaseDC(hwnd, hdc);
1023
1024 return hTargetImage;
1025}
1026
1027
1028/**************************************************************************
1029 * X11DRV_CLIPBOARD_ImportMetaFilePict
1030 *
1031 * Import MetaFilePict.
1032 */
1033HANDLE X11DRV_CLIPBOARD_ImportMetaFilePict(LPBYTE lpdata, UINT cBytes)
1034{
1035 return X11DRV_CLIPBOARD_SerializeMetafile(CF_METAFILEPICT, (HANDLE)lpdata, (LPDWORD)&cBytes, FALSE);
1036}
1037
1038
1039/**************************************************************************
1040 * X11DRV_ImportEnhMetaFile
1041 *
1042 * Import EnhMetaFile.
1043 */
1044HANDLE X11DRV_CLIPBOARD_ImportEnhMetaFile(LPBYTE lpdata, UINT cBytes)
1045{
1046 return X11DRV_CLIPBOARD_SerializeMetafile(CF_ENHMETAFILE, (HANDLE)lpdata, (LPDWORD)&cBytes, FALSE);
1047}
1048
1049
1050/**************************************************************************
1051 * X11DRV_ImportClipbordaData
1052 *
1053 * Generic import clipboard data routine.
1054 */
1055HANDLE X11DRV_CLIPBOARD_ImportClipboardData(LPBYTE lpdata, UINT cBytes)
1056{
1057 LPVOID lpClipData;
1058 HANDLE hClipData = 0;
1059
1060 if (cBytes)
1061 {
1062 /* Turn on the DDESHARE flag to enable shared 32 bit memory */
1063 hClipData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, cBytes);
1064 if ((lpClipData = GlobalLock(hClipData)))
1065 {
1066 memcpy(lpClipData, lpdata, cBytes);
1067 GlobalUnlock(hClipData);
1068 }
1069 else
1070 hClipData = 0;
1071 }
1072
1073 return hClipData;
1074}
1075
1076
1077/**************************************************************************
1078 * X11DRV_CLIPBOARD_ExportClipboardData
1079 *
1080 * Generic export clipboard data routine.
1081 */
Ulrich Czekalla18873e72003-07-08 21:02:51 +00001082HANDLE X11DRV_CLIPBOARD_ExportClipboardData(Window requestor, Atom aTarget,
1083 Atom rprop, LPWINE_CLIPDATA lpData, LPDWORD lpBytes)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001084{
1085 LPVOID lpClipData;
1086 UINT cBytes = 0;
1087 HANDLE hClipData = 0;
1088
1089 *lpBytes = 0; /* Assume failure */
1090
1091 if (!X11DRV_CLIPBOARD_RenderFormat(lpData))
1092 ERR("Failed to export %d format\n", lpData->wFormatID);
1093 else
1094 {
1095 cBytes = GlobalSize(lpData->hData32);
1096
1097 hClipData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, cBytes);
1098
1099 if ((lpClipData = GlobalLock(hClipData)))
1100 {
1101 LPVOID lpdata = GlobalLock(lpData->hData32);
1102
1103 memcpy(lpClipData, lpdata, cBytes);
1104 *lpBytes = cBytes;
1105
1106 GlobalUnlock(lpData->hData32);
1107 GlobalUnlock(hClipData);
1108 }
1109 }
1110
1111 return hClipData;
1112}
1113
1114
1115/**************************************************************************
1116 * X11DRV_CLIPBOARD_ExportXAString
1117 *
Ulrich Czekalla18873e72003-07-08 21:02:51 +00001118 * Export CF_UNICODE converting the string to XA_STRING.
1119 * Helper function for X11DRV_CLIPBOARD_ExportString.
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001120 */
1121HANDLE X11DRV_CLIPBOARD_ExportXAString(LPWINE_CLIPDATA lpData, LPDWORD lpBytes)
1122{
1123 INT i, j;
1124 UINT size;
1125 LPWSTR uni_text;
1126 LPSTR text, lpstr;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001127
1128 *lpBytes = 0; /* Assume return has zero bytes */
1129
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001130 uni_text = GlobalLock(lpData->hData32);
1131
Dmitry Timoshkov8a8d1b92003-07-09 04:22:57 +00001132 size = WideCharToMultiByte(CP_UNIXCP, 0, uni_text, -1, NULL, 0, NULL, NULL);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001133
1134 text = HeapAlloc(GetProcessHeap(), 0, size);
1135 if (!text)
1136 return None;
Dmitry Timoshkov8a8d1b92003-07-09 04:22:57 +00001137 WideCharToMultiByte(CP_UNIXCP, 0, uni_text, -1, text, size, NULL, NULL);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001138
1139 /* remove carriage returns */
1140
1141 lpstr = (char*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size-- );
1142 if(lpstr == NULL) return None;
1143 for(i = 0,j = 0; i < size && text[i]; i++ )
1144 {
1145 if( text[i] == '\r' &&
1146 (text[i+1] == '\n' || text[i+1] == '\0') ) continue;
1147 lpstr[j++] = text[i];
1148 }
1149 lpstr[j]='\0';
1150
1151 *lpBytes = j; /* Number of bytes in string */
1152
1153 HeapFree(GetProcessHeap(), 0, text);
1154 GlobalUnlock(lpData->hData32);
1155
1156 return lpstr;
1157}
1158
1159
1160/**************************************************************************
Ulrich Czekalla18873e72003-07-08 21:02:51 +00001161 * X11DRV_CLIPBOARD_ExportCompoundText
1162 *
1163 * Export CF_UNICODE to COMPOUND_TEXT or TEXT
1164 * Helper function for X11DRV_CLIPBOARD_ExportString.
1165 */
1166HANDLE X11DRV_CLIPBOARD_ExportCompoundText(Window requestor, Atom aTarget, Atom rprop,
1167 LPWINE_CLIPDATA lpData, LPDWORD lpBytes)
1168{
1169 Display *display = thread_display();
1170 char* lpstr = 0;
1171 XTextProperty prop;
1172 XICCEncodingStyle style;
1173
1174 lpstr = (char*) X11DRV_CLIPBOARD_ExportXAString(lpData, lpBytes);
1175
1176 if (lpstr)
1177 {
Alexandre Julliardd09c3282003-11-20 04:24:18 +00001178 if (aTarget == x11drv_atom(COMPOUND_TEXT))
Ulrich Czekalla18873e72003-07-08 21:02:51 +00001179 style = XCompoundTextStyle;
1180 else
1181 style = XStdICCTextStyle;
1182
1183 /* Update the X property */
1184 wine_tsx11_lock();
1185 if (XmbTextListToTextProperty(display, &lpstr, 1, style, &prop) == Success)
1186 {
1187 XSetTextProperty(display, requestor, &prop, rprop);
1188 XFree(prop.value);
1189 }
1190 wine_tsx11_unlock();
1191
1192 HeapFree( GetProcessHeap(), 0, lpstr );
1193 }
1194
1195 return 0;
1196}
1197
1198/**************************************************************************
1199 * X11DRV_CLIPBOARD_ExportString
1200 *
1201 * Export CF_UNICODE string
1202 */
1203HANDLE X11DRV_CLIPBOARD_ExportString(Window requestor, Atom aTarget, Atom rprop,
1204 LPWINE_CLIPDATA lpData, LPDWORD lpBytes)
1205{
1206 if (X11DRV_CLIPBOARD_RenderFormat(lpData))
1207 {
1208 if (aTarget == XA_STRING)
1209 return X11DRV_CLIPBOARD_ExportXAString(lpData, lpBytes);
Alexandre Julliardd09c3282003-11-20 04:24:18 +00001210 else if (aTarget == x11drv_atom(COMPOUND_TEXT) || aTarget == x11drv_atom(TEXT))
Ulrich Czekalla18873e72003-07-08 21:02:51 +00001211 return X11DRV_CLIPBOARD_ExportCompoundText(requestor, aTarget,
1212 rprop, lpData, lpBytes);
1213 else
1214 ERR("Unknown target %ld to %d format\n", aTarget, lpData->wFormatID);
1215 }
1216 else
1217 ERR("Failed to render %d format\n", lpData->wFormatID);
1218
1219 return 0;
1220}
1221
1222
1223/**************************************************************************
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001224 * X11DRV_CLIPBOARD_ExportXAPIXMAP
1225 *
1226 * Export CF_DIB to XA_PIXMAP.
1227 */
Ulrich Czekalla18873e72003-07-08 21:02:51 +00001228HANDLE X11DRV_CLIPBOARD_ExportXAPIXMAP(Window requestor, Atom aTarget, Atom rprop,
1229 LPWINE_CLIPDATA lpdata, LPDWORD lpBytes)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001230{
1231 HDC hdc;
1232 Pixmap pixmap;
1233
1234 if (!X11DRV_CLIPBOARD_RenderFormat(lpdata))
1235 {
1236 ERR("Failed to export %d format\n", lpdata->wFormatID);
1237 return 0;
1238 }
1239
1240 hdc = GetDC(0);
1241
1242 /* For convert from packed DIB to Pixmap */
1243 pixmap = X11DRV_DIB_CreatePixmapFromDIB(lpdata, hdc);
1244 *lpBytes = 4; /* pixmap is a 32bit value */
1245
1246 ReleaseDC(0, hdc);
1247
1248 return (HANDLE) pixmap;
1249}
1250
1251
1252/**************************************************************************
1253 * X11DRV_CLIPBOARD_ExportMetaFilePict
1254 *
1255 * Export MetaFilePict.
1256 */
Ulrich Czekalla18873e72003-07-08 21:02:51 +00001257HANDLE X11DRV_CLIPBOARD_ExportMetaFilePict(Window requestor, Atom aTarget, Atom rprop,
1258 LPWINE_CLIPDATA lpdata, LPDWORD lpBytes)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001259{
1260 if (!X11DRV_CLIPBOARD_RenderFormat(lpdata))
1261 {
1262 ERR("Failed to export %d format\n", lpdata->wFormatID);
1263 return 0;
1264 }
1265
1266 return X11DRV_CLIPBOARD_SerializeMetafile(CF_METAFILEPICT, (HANDLE)lpdata->hData32,
1267 lpBytes, TRUE);
1268}
1269
1270
1271/**************************************************************************
1272 * X11DRV_CLIPBOARD_ExportEnhMetaFile
1273 *
1274 * Export EnhMetaFile.
1275 */
Ulrich Czekalla18873e72003-07-08 21:02:51 +00001276HANDLE X11DRV_CLIPBOARD_ExportEnhMetaFile(Window requestor, Atom aTarget, Atom rprop,
1277 LPWINE_CLIPDATA lpdata, LPDWORD lpBytes)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001278{
1279 if (!X11DRV_CLIPBOARD_RenderFormat(lpdata))
1280 {
1281 ERR("Failed to export %d format\n", lpdata->wFormatID);
1282 return 0;
1283 }
1284
1285 return X11DRV_CLIPBOARD_SerializeMetafile(CF_ENHMETAFILE, (HANDLE)lpdata->hData32,
1286 lpBytes, TRUE);
1287}
1288
1289
1290/**************************************************************************
1291 * X11DRV_CLIPBOARD_QueryTargets
1292 */
1293static BOOL X11DRV_CLIPBOARD_QueryTargets(Display *display, Window w, Atom selection, XEvent *xe)
1294{
1295 INT i;
1296 Bool res;
1297
1298 wine_tsx11_lock();
Alexandre Julliardd09c3282003-11-20 04:24:18 +00001299 XConvertSelection(display, selection, x11drv_atom(TARGETS),
1300 x11drv_atom(SELECTION_DATA), w, CurrentTime);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001301 wine_tsx11_unlock();
1302
1303 /*
1304 * Wait until SelectionNotify is received
1305 */
1306 for (i = 0; i < SELECTION_RETRIES; i++)
1307 {
1308 wine_tsx11_lock();
1309 res = XCheckTypedWindowEvent(display, w, SelectionNotify, xe);
1310 wine_tsx11_unlock();
1311 if (res && xe->xselection.selection == selection) break;
1312
1313 usleep(SELECTION_WAIT);
1314 }
1315
1316 /* Verify that the selection returned a valid TARGETS property */
Alexandre Julliardd09c3282003-11-20 04:24:18 +00001317 if ((xe->xselection.target != x11drv_atom(TARGETS)) || (xe->xselection.property == None))
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001318 {
1319 /* Selection owner failed to respond or we missed the SelectionNotify */
1320 WARN("Failed to retrieve TARGETS for selection %ld.\n", selection);
1321 return FALSE;
1322 }
1323
1324 return TRUE;
1325}
1326
1327
1328/**************************************************************************
1329 * X11DRV_CLIPBOARD_QueryAvailableData
Noel Borthwick29700671999-09-03 15:17:57 +00001330 *
1331 * Caches the list of data formats available from the current selection.
1332 * This queries the selection owner for the TARGETS property and saves all
1333 * reported property types.
1334 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001335static int X11DRV_CLIPBOARD_QueryAvailableData(LPCLIPBOARDINFO lpcbinfo)
Noel Borthwick29700671999-09-03 15:17:57 +00001336{
Alexandre Julliard43230042001-05-16 19:52:29 +00001337 Display *display = thread_display();
Noel Borthwick29700671999-09-03 15:17:57 +00001338 XEvent xe;
Noel Borthwick29700671999-09-03 15:17:57 +00001339 Atom atype=AnyPropertyType;
1340 int aformat;
1341 unsigned long remain;
1342 Atom* targetList=NULL;
1343 Window w;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001344 HWND hWndClipWindow;
1345 unsigned long cSelectionTargets = 0;
Vincent Béron9a624912002-05-31 23:06:46 +00001346
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001347 if (selectionAcquired & (S_PRIMARY | S_CLIPBOARD))
1348 {
1349 ERR("Received request to cache selection but process is owner=(%08x)\n",
1350 (unsigned) selectionWindow);
Noel Borthwick29700671999-09-03 15:17:57 +00001351
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001352 selectionAcquired = S_NOSELECTION;
Vincent Béron9a624912002-05-31 23:06:46 +00001353
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001354 if (TSXGetSelectionOwner(display,XA_PRIMARY) == selectionWindow)
1355 selectionAcquired |= S_PRIMARY;
Noel Borthwick29700671999-09-03 15:17:57 +00001356
Alexandre Julliardd09c3282003-11-20 04:24:18 +00001357 if (TSXGetSelectionOwner(display,x11drv_atom(CLIPBOARD)) == selectionWindow)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001358 selectionAcquired |= S_CLIPBOARD;
1359
1360 if (!(selectionAcquired == (S_PRIMARY | S_CLIPBOARD)))
1361 {
1362 WARN("Lost selection but process didn't process SelectClear\n");
1363 selectionWindow = None;
1364 }
1365 else
1366 {
Ulrich Czekalla18873e72003-07-08 21:02:51 +00001367 return -1; /* Prevent self request */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001368 }
1369 }
1370
1371 if (lpcbinfo->flags & CB_OWNER)
1372 hWndClipWindow = lpcbinfo->hWndOwner;
1373 else if (lpcbinfo->flags & CB_OPEN)
1374 hWndClipWindow = lpcbinfo->hWndOpen;
1375 else
1376 hWndClipWindow = GetActiveWindow();
1377
1378 if (!hWndClipWindow)
1379 {
1380 WARN("No window available to retrieve selection!n");
Ulrich Czekalla18873e72003-07-08 21:02:51 +00001381 return -1;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001382 }
1383
1384 w = X11DRV_get_whole_window(GetAncestor(hWndClipWindow, GA_ROOT));
Noel Borthwick29700671999-09-03 15:17:57 +00001385
1386 /*
1387 * Query the selection owner for the TARGETS property
1388 */
Ulrich Czekalla18873e72003-07-08 21:02:51 +00001389 if (TSXGetSelectionOwner(display,XA_PRIMARY) ||
Alexandre Julliardd09c3282003-11-20 04:24:18 +00001390 TSXGetSelectionOwner(display,x11drv_atom(CLIPBOARD)))
Ulrich Czekalla18873e72003-07-08 21:02:51 +00001391 {
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001392 if (X11DRV_CLIPBOARD_QueryTargets(display, w, XA_PRIMARY, &xe))
1393 selectionCacheSrc = XA_PRIMARY;
Alexandre Julliardd09c3282003-11-20 04:24:18 +00001394 else if (X11DRV_CLIPBOARD_QueryTargets(display, w, x11drv_atom(CLIPBOARD), &xe))
1395 selectionCacheSrc = x11drv_atom(CLIPBOARD);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001396 else
Ulrich Czekalla18873e72003-07-08 21:02:51 +00001397 return -1;
1398 }
1399 else /* No selection owner so report 0 targets available */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001400 return 0;
Noel Borthwick29700671999-09-03 15:17:57 +00001401
1402 /* Read the TARGETS property contents */
1403 if(TSXGetWindowProperty(display, xe.xselection.requestor, xe.xselection.property,
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001404 0, 0x3FFF, True, AnyPropertyType/*XA_ATOM*/, &atype, &aformat, &cSelectionTargets,
1405 &remain, (unsigned char**)&targetList) != Success)
1406 {
1407 WARN("Failed to read TARGETS property\n");
1408 }
Noel Borthwick29700671999-09-03 15:17:57 +00001409 else
1410 {
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +00001411 TRACE("Type %lx,Format %d,nItems %ld, Remain %ld\n",
1412 atype, aformat, cSelectionTargets, remain);
Noel Borthwick29700671999-09-03 15:17:57 +00001413 /*
1414 * The TARGETS property should have returned us a list of atoms
1415 * corresponding to each selection target format supported.
1416 */
Alexandre Julliardd09c3282003-11-20 04:24:18 +00001417 if ((atype == XA_ATOM || atype == x11drv_atom(TARGETS)) && aformat == 32)
Noel Borthwick29700671999-09-03 15:17:57 +00001418 {
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +00001419 INT i, nb_atoms = 0;
1420 Atom *atoms = NULL;
Vincent Béron9a624912002-05-31 23:06:46 +00001421
Noel Borthwick29700671999-09-03 15:17:57 +00001422 /* Cache these formats in the clipboard cache */
Noel Borthwick29700671999-09-03 15:17:57 +00001423 for (i = 0; i < cSelectionTargets; i++)
1424 {
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001425 LPWINE_CLIPFORMAT lpFormat = X11DRV_CLIPBOARD_LookupProperty(targetList[i]);
Noel Borthwick29700671999-09-03 15:17:57 +00001426
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001427 if (!lpFormat)
1428 lpFormat = X11DRV_CLIPBOARD_LookupAliasProperty(targetList[i]);
1429
1430 if (!lpFormat)
Noel Borthwick29700671999-09-03 15:17:57 +00001431 {
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +00001432 /* add it to the list of atoms that we don't know about yet */
1433 if (!atoms) atoms = HeapAlloc( GetProcessHeap(), 0,
1434 (cSelectionTargets - i) * sizeof(*atoms) );
1435 if (atoms) atoms[nb_atoms++] = targetList[i];
Noel Borthwick29700671999-09-03 15:17:57 +00001436 }
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +00001437 else
1438 {
1439 TRACE("Atom#%d Property(%d): --> FormatID(%d) %s\n",
1440 i, lpFormat->drvData, lpFormat->wFormatID, lpFormat->Name);
1441 X11DRV_CLIPBOARD_InsertClipboardData(lpFormat->wFormatID, 0, 0, 0);
1442 }
1443 }
Vincent Béron9a624912002-05-31 23:06:46 +00001444
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +00001445 /* query all unknown atoms in one go */
1446 if (atoms)
1447 {
1448 char **names = HeapAlloc( GetProcessHeap(), 0, nb_atoms * sizeof(*names) );
1449 if (names)
1450 {
1451 wine_tsx11_lock();
1452 XGetAtomNames( display, atoms, nb_atoms, names );
1453 wine_tsx11_unlock();
1454 for (i = 0; i < nb_atoms; i++)
1455 {
1456 WINE_CLIPFORMAT *lpFormat = register_format( names[i], atoms[i] );
1457 if (!lpFormat)
1458 {
1459 ERR("Failed to cache %s property\n", names[i]);
1460 continue;
1461 }
1462 TRACE("Atom#%d Property(%d): --> FormatID(%d) %s\n",
1463 i, lpFormat->drvData, lpFormat->wFormatID, lpFormat->Name);
1464 X11DRV_CLIPBOARD_InsertClipboardData(lpFormat->wFormatID, 0, 0, 0);
1465 }
1466 wine_tsx11_lock();
1467 for (i = 0; i < nb_atoms; i++) XFree( names[i] );
1468 wine_tsx11_unlock();
1469 HeapFree( GetProcessHeap(), 0, names );
1470 }
Noel Borthwick29700671999-09-03 15:17:57 +00001471 }
1472 }
1473
1474 /* Free the list of targets */
1475 TSXFree(targetList);
1476 }
Gerard Patel9289a5d2000-12-22 23:26:18 +00001477
Noel Borthwick29700671999-09-03 15:17:57 +00001478 return cSelectionTargets;
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001479}
1480
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001481
1482/**************************************************************************
1483 * X11DRV_CLIPBOARD_ReadClipboardData
1484 *
1485 * This method is invoked only when we DO NOT own the X selection
1486 *
1487 * We always get the data from the selection client each time,
1488 * since we have no way of determining if the data in our cache is stale.
1489 */
1490static BOOL X11DRV_CLIPBOARD_ReadClipboardData(UINT wFormat)
1491{
1492 Display *display = thread_display();
1493 BOOL bRet = FALSE;
1494 Bool res;
1495
1496 HWND hWndClipWindow = GetOpenClipboardWindow();
1497 HWND hWnd = (hWndClipWindow) ? hWndClipWindow : GetActiveWindow();
1498
1499 LPWINE_CLIPFORMAT lpFormat;
1500
1501 TRACE("%d\n", wFormat);
1502
1503 if (!selectionAcquired)
1504 {
1505 Window w = X11DRV_get_whole_window(GetAncestor(hWnd, GA_ROOT));
1506 if(!w)
1507 {
1508 FIXME("No parent win found %p %p\n", hWnd, hWndClipWindow);
1509 return FALSE;
1510 }
1511
1512 lpFormat = X11DRV_CLIPBOARD_LookupFormat(wFormat);
1513
1514 if (lpFormat->drvData)
1515 {
1516 DWORD i;
1517 UINT alias;
1518 XEvent xe;
1519
1520 TRACE("Requesting %s selection (%d) from win(%08x)\n",
1521 lpFormat->Name, lpFormat->drvData, (UINT)selectionCacheSrc);
1522
1523 wine_tsx11_lock();
1524 XConvertSelection(display, selectionCacheSrc, lpFormat->drvData,
Alexandre Julliardd09c3282003-11-20 04:24:18 +00001525 x11drv_atom(SELECTION_DATA), w, CurrentTime);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001526 wine_tsx11_unlock();
1527
1528 /* wait until SelectionNotify is received */
1529 for (i = 0; i < SELECTION_RETRIES; i++)
1530 {
1531 wine_tsx11_lock();
1532 res = XCheckTypedWindowEvent(display, w, SelectionNotify, &xe);
1533 wine_tsx11_unlock();
1534 if (res && xe.xselection.selection == selectionCacheSrc) break;
1535
1536 usleep(SELECTION_WAIT);
1537 }
1538
1539 /* If the property wasn't available check for aliases */
1540 if (xe.xselection.property == None &&
1541 (alias = X11DRV_CLIPBOARD_LookupPropertyAlias(lpFormat->drvData)))
1542 {
1543 wine_tsx11_lock();
1544 XConvertSelection(display, selectionCacheSrc, alias,
Alexandre Julliardd09c3282003-11-20 04:24:18 +00001545 x11drv_atom(SELECTION_DATA), w, CurrentTime);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001546 wine_tsx11_unlock();
1547
1548 /* wait until SelectionNotify is received */
1549 for (i = 0; i < SELECTION_RETRIES; i++)
1550 {
1551 wine_tsx11_lock();
1552 res = XCheckTypedWindowEvent(display, w, SelectionNotify, &xe);
1553 wine_tsx11_unlock();
1554 if (res && xe.xselection.selection == selectionCacheSrc) break;
1555
1556 usleep(SELECTION_WAIT);
1557 }
1558 }
1559
1560 /* Verify that the selection returned a valid TARGETS property */
1561 if (xe.xselection.property != None)
1562 {
1563 /*
1564 * Read the contents of the X selection property
1565 * into WINE's clipboard cache converting the
1566 * selection to be compatible if possible.
1567 */
1568 bRet = X11DRV_CLIPBOARD_ReadSelection(lpFormat, xe.xselection.requestor,
1569 xe.xselection.property);
1570 }
1571 }
1572 }
1573 else
1574 {
1575 ERR("Received request to cache selection data but process is owner\n");
1576 }
1577
1578 TRACE("Returning %d\n", bRet);
1579
1580 return bRet;
1581}
1582
1583
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001584/**************************************************************************
1585 * X11DRV_CLIPBOARD_ReadSelection
Noel Borthwick29700671999-09-03 15:17:57 +00001586 * Reads the contents of the X selection property into the WINE clipboard cache
1587 * converting the selection into a format compatible with the windows clipboard
1588 * if possible.
1589 * This method is invoked only to read the contents of a the selection owned
1590 * by an external application. i.e. when we do not own the X selection.
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001591 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001592static BOOL X11DRV_CLIPBOARD_ReadSelection(LPWINE_CLIPFORMAT lpData, Window w, Atom prop)
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001593{
Alexandre Julliard43230042001-05-16 19:52:29 +00001594 Display *display = thread_display();
Noel Borthwick29700671999-09-03 15:17:57 +00001595 Atom atype=AnyPropertyType;
1596 int aformat;
Aric Stewart278dd152001-02-23 01:31:47 +00001597 unsigned long total,nitems,remain,itemSize,val_cnt;
1598 long lRequestLength,bwc;
1599 unsigned char* val;
1600 unsigned char* buffer;
Noel Borthwick29700671999-09-03 15:17:57 +00001601 BOOL bRet = FALSE;
Vincent Béron9a624912002-05-31 23:06:46 +00001602
Noel Borthwick29700671999-09-03 15:17:57 +00001603 if(prop == None)
1604 return bRet;
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001605
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001606 TRACE("Reading X selection type %s\n", lpData->Name);
Noel Borthwick29700671999-09-03 15:17:57 +00001607
1608 /*
Noel Borthwick29700671999-09-03 15:17:57 +00001609 * First request a zero length in order to figure out the request size.
1610 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001611 if(TSXGetWindowProperty(display,w,prop,0,0,False, AnyPropertyType,
1612 &atype, &aformat, &nitems, &itemSize, &val) != Success)
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001613 {
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001614 WARN("Failed to get property size\n");
Noel Borthwick29700671999-09-03 15:17:57 +00001615 return bRet;
1616 }
Noel Borthwickd05b7be1999-09-20 15:42:47 +00001617
1618 /* Free zero length return data if any */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001619 if (val)
Noel Borthwick29700671999-09-03 15:17:57 +00001620 {
1621 TSXFree(val);
1622 val = NULL;
1623 }
Vincent Béron9a624912002-05-31 23:06:46 +00001624
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001625 TRACE("Retrieving %ld bytes\n", itemSize * aformat/8);
1626
Noel Borthwick29700671999-09-03 15:17:57 +00001627 lRequestLength = (itemSize * aformat/8)/4 + 1;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001628 bwc = aformat/8;
Aric Stewart278dd152001-02-23 01:31:47 +00001629
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001630 /* Read property in 4K blocks */
1631 if (TSXGetWindowProperty(display,w,prop,0,4096,False, AnyPropertyType/*reqType*/,
1632 &atype, &aformat, &nitems, &remain, &buffer) != Success)
Noel Borthwick29700671999-09-03 15:17:57 +00001633 {
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001634 WARN("Failed to read property\n");
Noel Borthwick29700671999-09-03 15:17:57 +00001635 return bRet;
1636 }
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001637
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001638 val = (char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nitems*bwc);
1639 memcpy(val,buffer,nitems*bwc);
1640
1641 TSXFree(buffer);
1642
1643 for (total = nitems*bwc, val_cnt = 0; remain;)
1644 {
Aric Stewart278dd152001-02-23 01:31:47 +00001645 val_cnt +=nitems*bwc;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001646 if (TSXGetWindowProperty(display, w, prop, (total / 4), 4096, False,
1647 AnyPropertyType, &atype, &aformat, &nitems, &remain, &buffer) != Success)
1648 {
1649 WARN("Failed to read property\n");
1650 HeapFree(GetProcessHeap(), 0, val);
1651 return bRet;
1652 }
Aric Stewart278dd152001-02-23 01:31:47 +00001653
1654 total += nitems*bwc;
1655 HeapReAlloc(GetProcessHeap(),0,val, total);
1656 memcpy(&val[val_cnt], buffer, nitems*(aformat/8));
1657 TSXFree(buffer);
Noel Borthwick29700671999-09-03 15:17:57 +00001658 }
Vincent Béron9a624912002-05-31 23:06:46 +00001659
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001660 bRet = X11DRV_CLIPBOARD_InsertClipboardData(lpData->wFormatID, 0, lpData->lpDrvImportFunc(val, total), 0);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001661
Noel Borthwickd05b7be1999-09-20 15:42:47 +00001662 /* Delete the property on the window now that we are done
1663 * This will send a PropertyNotify event to the selection owner. */
Alexandre Julliard2496c082003-11-21 00:17:33 +00001664 wine_tsx11_lock();
1665 XDeleteProperty(display,w,prop);
1666 wine_tsx11_unlock();
Vincent Béron9a624912002-05-31 23:06:46 +00001667
Noel Borthwickd05b7be1999-09-20 15:42:47 +00001668 /* Free the retrieved property data */
Aric Stewart278dd152001-02-23 01:31:47 +00001669 HeapFree(GetProcessHeap(),0,val);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001670
Noel Borthwick29700671999-09-03 15:17:57 +00001671 return bRet;
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001672}
1673
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001674
1675/**************************************************************************
1676 * CLIPBOARD_SerializeMetafile
1677 */
1678static HANDLE X11DRV_CLIPBOARD_SerializeMetafile(INT wformat, HANDLE hdata, LPDWORD lpcbytes, BOOL out)
1679{
1680 HANDLE h = 0;
1681
1682 TRACE(" wFormat=%d hdata=%08x out=%d\n", wformat, (unsigned int) hdata, out);
1683
1684 if (out) /* Serialize out, caller should free memory */
1685 {
1686 *lpcbytes = 0; /* Assume failure */
1687
1688 if (wformat == CF_METAFILEPICT)
1689 {
1690 LPMETAFILEPICT lpmfp = (LPMETAFILEPICT) GlobalLock(hdata);
1691 int size = GetMetaFileBitsEx(lpmfp->hMF, 0, NULL);
1692
1693 h = GlobalAlloc(0, size + sizeof(METAFILEPICT));
1694 if (h)
1695 {
1696 char *pdata = GlobalLock(h);
1697
1698 memcpy(pdata, lpmfp, sizeof(METAFILEPICT));
1699 GetMetaFileBitsEx(lpmfp->hMF, size, pdata + sizeof(METAFILEPICT));
1700
1701 *lpcbytes = size + sizeof(METAFILEPICT);
1702
1703 GlobalUnlock(h);
1704 }
1705
1706 GlobalUnlock(hdata);
1707 }
1708 else if (wformat == CF_ENHMETAFILE)
1709 {
1710 int size = GetEnhMetaFileBits(hdata, 0, NULL);
1711
1712 h = GlobalAlloc(0, size);
1713 if (h)
1714 {
1715 LPVOID pdata = GlobalLock(h);
1716
1717 GetEnhMetaFileBits(hdata, size, pdata);
1718 *lpcbytes = size;
1719
1720 GlobalUnlock(h);
1721 }
1722 }
1723 }
1724 else
1725 {
1726 if (wformat == CF_METAFILEPICT)
1727 {
1728 h = GlobalAlloc(0, sizeof(METAFILEPICT));
1729 if (h)
1730 {
1731 LPMETAFILEPICT pmfp = (LPMETAFILEPICT) GlobalLock(h);
1732
1733 memcpy(pmfp, (LPVOID)hdata, sizeof(METAFILEPICT));
1734 pmfp->hMF = SetMetaFileBitsEx(*lpcbytes - sizeof(METAFILEPICT),
1735 (char *)hdata + sizeof(METAFILEPICT));
1736
1737 GlobalUnlock(h);
1738 }
1739 }
1740 else if (wformat == CF_ENHMETAFILE)
1741 {
1742 h = SetEnhMetaFileBits(*lpcbytes, (LPVOID)hdata);
1743 }
1744 }
1745
1746 return h;
1747}
1748
1749
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001750/**************************************************************************
1751 * X11DRV_CLIPBOARD_ReleaseSelection
1752 *
Noel Borthwick29700671999-09-03 15:17:57 +00001753 * Release an XA_PRIMARY or XA_CLIPBOARD selection that we own, in response
1754 * to a SelectionClear event.
1755 * This can occur in response to another client grabbing the X selection.
Francis Beaudet56ab55d1999-10-24 20:22:24 +00001756 * If the XA_CLIPBOARD selection is lost, we relinquish XA_PRIMARY as well.
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001757 */
Noel Borthwick29700671999-09-03 15:17:57 +00001758void X11DRV_CLIPBOARD_ReleaseSelection(Atom selType, Window w, HWND hwnd)
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001759{
Alexandre Julliard43230042001-05-16 19:52:29 +00001760 Display *display = thread_display();
Vincent Béron9a624912002-05-31 23:06:46 +00001761
Francis Beaudet56ab55d1999-10-24 20:22:24 +00001762 /* w is the window that lost the selection
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001763 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001764 TRACE("event->window = %08x (selectionWindow = %08x) selectionAcquired=0x%08x\n",
1765 (unsigned)w, (unsigned)selectionWindow, (unsigned)selectionAcquired);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001766
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001767 if (selectionAcquired)
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001768 {
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001769 if (w == selectionWindow)
1770 {
Francis Beaudet56ab55d1999-10-24 20:22:24 +00001771 /* If we're losing the CLIPBOARD selection, or if the preferences in .winerc
1772 * dictate that *all* selections should be cleared on loss of a selection,
1773 * we must give up all the selections we own.
1774 */
Alexandre Julliardd09c3282003-11-20 04:24:18 +00001775 if (clearAllSelections || (selType == x11drv_atom(CLIPBOARD)))
Noel Borthwick29700671999-09-03 15:17:57 +00001776 {
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001777 CLIPBOARDINFO cbinfo;
Francis Beaudet56ab55d1999-10-24 20:22:24 +00001778
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001779 /* completely give up the selection */
1780 TRACE("Lost CLIPBOARD (+PRIMARY) selection\n");
Vincent Béron9a624912002-05-31 23:06:46 +00001781
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001782 /* We are completely giving up the selection. There is a
1783 * potential race condition where the apps that now owns
1784 * the selection has already grabbed both selections. In
1785 * this case, if we clear any selection we may clear the
1786 * new owners selection. To prevent this common case we
1787 * try to open the clipboard. If we can't, we assume it
Ulrich Czekalla18873e72003-07-08 21:02:51 +00001788 * was a wine apps that took it and has taken both selections.
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001789 * In this case, don't bother releasing the other selection.
1790 * Otherwise only release the selection if we still own it.
Noel Borthwick29700671999-09-03 15:17:57 +00001791 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001792 X11DRV_CLIPBOARD_GetClipboardInfo(&cbinfo);
Noel Borthwick29700671999-09-03 15:17:57 +00001793
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001794 if (cbinfo.flags & CB_OWNER)
1795 {
1796 /* Since we're still the owner, this wasn't initiated by
1797 another Wine process */
1798 if (OpenClipboard(hwnd))
1799 {
1800 /* We really lost CLIPBOARD but want to voluntarily lose PRIMARY */
Alexandre Julliardd09c3282003-11-20 04:24:18 +00001801 if ((selType == x11drv_atom(CLIPBOARD)) && (selectionAcquired & S_PRIMARY))
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001802 {
1803 TRACE("Lost clipboard. Check if we need to release PRIMARY\n");
1804 if (selectionWindow == TSXGetSelectionOwner(display,XA_PRIMARY))
1805 {
1806 TRACE("We still own PRIMARY. Releasing PRIMARY.\n");
1807 XSetSelectionOwner(display, XA_PRIMARY, None, CurrentTime);
1808 }
1809 else
1810 TRACE("We no longer own PRIMARY\n");
1811 }
Francis Beaudet56ab55d1999-10-24 20:22:24 +00001812
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001813 /* We really lost PRIMARY but want to voluntarily lose CLIPBOARD */
1814 if ((selType == XA_PRIMARY) && (selectionAcquired & S_CLIPBOARD))
1815 {
1816 TRACE("Lost PRIMARY. Check if we need to release CLIPBOARD\n");
Alexandre Julliardd09c3282003-11-20 04:24:18 +00001817 if (selectionWindow == TSXGetSelectionOwner(display,x11drv_atom(CLIPBOARD)))
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001818 {
1819 TRACE("We still own CLIPBOARD. Releasing CLIPBOARD.\n");
Alexandre Julliardd09c3282003-11-20 04:24:18 +00001820 XSetSelectionOwner(display, x11drv_atom(CLIPBOARD), None, CurrentTime);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001821 }
1822 else
1823 TRACE("We no longer own CLIPBOARD\n");
1824 }
1825
1826 /* Destroy private objects */
1827 SendMessageW(cbinfo.hWndOwner, WM_DESTROYCLIPBOARD, 0, 0);
1828
1829 /* Give up ownership of the windows clipboard */
1830 X11DRV_CLIPBOARD_ReleaseOwnership();
1831
1832 CloseClipboard();
1833 }
1834 }
1835 else
1836 {
1837 TRACE("Lost selection to other Wine process.\n");
1838 }
1839
1840 selectionWindow = None;
1841 PrimarySelectionOwner = ClipboardSelectionOwner = 0;
1842
1843 X11DRV_EmptyClipboard();
1844
1845 /* Reset the selection flags now that we are done */
1846 selectionAcquired = S_NOSELECTION;
Noel Borthwick29700671999-09-03 15:17:57 +00001847 }
1848 else if ( selType == XA_PRIMARY ) /* Give up only PRIMARY selection */
1849 {
1850 TRACE("Lost PRIMARY selection\n");
1851 PrimarySelectionOwner = 0;
1852 selectionAcquired &= ~S_PRIMARY; /* clear S_PRIMARY mask */
1853 }
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001854 }
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001855 }
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001856}
1857
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001858
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001859/**************************************************************************
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001860 * IsSelectionOwner (X11DRV.@)
1861 *
1862 * Returns: TRUE if the selection is owned by this process, FALSE otherwise
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001863 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001864static BOOL X11DRV_CLIPBOARD_IsSelectionOwner(void)
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001865{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001866 return selectionAcquired;
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001867}
1868
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001869
1870/**************************************************************************
1871 * X11DRV Clipboard Exports
1872 **************************************************************************/
1873
1874
1875/**************************************************************************
1876 * RegisterClipboardFormat (X11DRV.@)
1877 *
1878 * Registers a custom X clipboard format
1879 * Returns: Format id or 0 on failure
1880 */
1881INT X11DRV_RegisterClipboardFormat(LPCSTR FormatName)
1882{
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +00001883 LPWINE_CLIPFORMAT lpFormat;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001884
Alexandre Julliard3f6cb0c2003-11-21 05:23:17 +00001885 if (FormatName == NULL) return 0;
1886 if (!(lpFormat = register_format( FormatName, 0 ))) return 0;
1887 return lpFormat->wFormatID;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001888}
1889
1890
1891/**************************************************************************
1892 * X11DRV_GetClipboardFormatName
1893 */
1894INT X11DRV_GetClipboardFormatName(UINT wFormat, LPSTR retStr, INT maxlen)
1895{
1896 INT len = 0;
1897 LPWINE_CLIPFORMAT lpFormat = X11DRV_CLIPBOARD_LookupFormat(wFormat);
1898
1899 TRACE("(%04X, %p, %d) !\n", wFormat, retStr, maxlen);
1900
1901 if (!lpFormat || (lpFormat->wFlags & CF_FLAG_BUILTINFMT))
1902 {
1903 TRACE("Unknown format 0x%08x!\n", wFormat);
1904 SetLastError(ERROR_INVALID_PARAMETER);
1905 }
1906 else
1907 {
1908 strncpy(retStr, lpFormat->Name, maxlen - 1);
1909 retStr[maxlen - 1] = 0;
1910
1911 len = strlen(retStr);
1912 }
1913
1914 return len;
1915}
1916
1917
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001918/**************************************************************************
Patrik Stridvalldf75e892001-02-12 03:49:07 +00001919 * AcquireClipboard (X11DRV.@)
Noel Borthwick29700671999-09-03 15:17:57 +00001920 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001921void X11DRV_AcquireClipboard(HWND hWndClipWindow)
Noel Borthwick29700671999-09-03 15:17:57 +00001922{
Alexandre Julliard43230042001-05-16 19:52:29 +00001923 Display *display = thread_display();
Noel Borthwick29700671999-09-03 15:17:57 +00001924
1925 /*
1926 * Acquire X selection if we don't already own it.
1927 * Note that we only acquire the selection if it hasn't been already
1928 * acquired by us, and ignore the fact that another X window may be
1929 * asserting ownership. The reason for this is we need *any* top level
1930 * X window to hold selection ownership. The actual clipboard data requests
1931 * are made via GetClipboardData from EVENT_SelectionRequest and this
1932 * ensures that the real HWND owner services the request.
1933 * If the owning X window gets destroyed the selection ownership is
1934 * re-cycled to another top level X window in X11DRV_CLIPBOARD_ResetOwner.
1935 *
1936 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001937 if (!(selectionAcquired == (S_PRIMARY | S_CLIPBOARD)))
Noel Borthwick29700671999-09-03 15:17:57 +00001938 {
Ulrich Czekalla18873e72003-07-08 21:02:51 +00001939 Window owner;
1940
1941 if (!hWndClipWindow)
1942 hWndClipWindow = GetActiveWindow();
1943
1944 owner = X11DRV_get_whole_window(GetAncestor(hWndClipWindow, GA_ROOT));
Noel Borthwick29700671999-09-03 15:17:57 +00001945
1946 /* Grab PRIMARY selection if not owned */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001947 if (!(selectionAcquired & S_PRIMARY))
Noel Borthwick29700671999-09-03 15:17:57 +00001948 TSXSetSelectionOwner(display, XA_PRIMARY, owner, CurrentTime);
Vincent Béron9a624912002-05-31 23:06:46 +00001949
Noel Borthwick29700671999-09-03 15:17:57 +00001950 /* Grab CLIPBOARD selection if not owned */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001951 if (!(selectionAcquired & S_CLIPBOARD))
Alexandre Julliardd09c3282003-11-20 04:24:18 +00001952 TSXSetSelectionOwner(display, x11drv_atom(CLIPBOARD), owner, CurrentTime);
Noel Borthwick29700671999-09-03 15:17:57 +00001953
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001954 if (TSXGetSelectionOwner(display,XA_PRIMARY) == owner)
Noel Borthwick29700671999-09-03 15:17:57 +00001955 selectionAcquired |= S_PRIMARY;
1956
Alexandre Julliardd09c3282003-11-20 04:24:18 +00001957 if (TSXGetSelectionOwner(display,x11drv_atom(CLIPBOARD)) == owner)
Noel Borthwick29700671999-09-03 15:17:57 +00001958 selectionAcquired |= S_CLIPBOARD;
1959
1960 if (selectionAcquired)
1961 {
1962 selectionWindow = owner;
1963 TRACE("Grabbed X selection, owner=(%08x)\n", (unsigned) owner);
1964 }
1965 }
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001966 else
1967 {
1968 WARN("Received request to acquire selection but process is already owner=(%08x)\n", (unsigned) selectionWindow);
1969
1970 selectionAcquired = S_NOSELECTION;
1971
1972 if (TSXGetSelectionOwner(display,XA_PRIMARY) == selectionWindow)
1973 selectionAcquired |= S_PRIMARY;
1974
Alexandre Julliardd09c3282003-11-20 04:24:18 +00001975 if (TSXGetSelectionOwner(display,x11drv_atom(CLIPBOARD)) == selectionWindow)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001976 selectionAcquired |= S_CLIPBOARD;
1977
1978 if (!(selectionAcquired == (S_PRIMARY | S_CLIPBOARD)))
1979 {
1980 WARN("Lost selection but process didn't process SelectClear\n");
1981 selectionWindow = None;
1982 }
1983 }
Noel Borthwick29700671999-09-03 15:17:57 +00001984}
1985
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001986
Noel Borthwick29700671999-09-03 15:17:57 +00001987/**************************************************************************
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00001988 * X11DRV_EmptyClipboard
1989 */
1990void X11DRV_EmptyClipboard(void)
1991{
1992 if (ClipData)
1993 {
1994 LPWINE_CLIPDATA lpData;
1995 LPWINE_CLIPDATA lpNext = ClipData;
1996
1997 do
1998 {
1999 lpData = lpNext;
2000 lpNext = lpData->NextData;
2001 lpData->PrevData->NextData = lpData->NextData;
2002 lpData->NextData->PrevData = lpData->PrevData;
2003 X11DRV_CLIPBOARD_FreeData(lpData);
2004 HeapFree(GetProcessHeap(), 0, lpData);
2005 } while (lpNext != lpData);
2006 }
2007
2008 TRACE(" %d entries deleted from cache.\n", ClipDataCount);
2009
2010 ClipData = NULL;
2011 ClipDataCount = 0;
2012}
2013
2014
2015
2016/**************************************************************************
2017 * X11DRV_SetClipboardData
2018 */
2019BOOL X11DRV_SetClipboardData(UINT wFormat, HANDLE16 hData16, HANDLE hData32)
2020{
2021 BOOL bResult = FALSE;
2022
2023 if (X11DRV_CLIPBOARD_InsertClipboardData(wFormat, hData16, hData32, 0))
2024 bResult = TRUE;
2025
2026 return bResult;
2027}
2028
2029
2030/**************************************************************************
2031 * CountClipboardFormats
2032 */
2033INT X11DRV_CountClipboardFormats(void)
2034{
2035 CLIPBOARDINFO cbinfo;
2036
2037 X11DRV_CLIPBOARD_UpdateCache(&cbinfo);
2038
2039 TRACE(" count=%d\n", ClipDataCount);
2040
2041 return ClipDataCount;
2042}
2043
2044
2045/**************************************************************************
2046 * X11DRV_EnumClipboardFormats
2047 */
2048UINT X11DRV_EnumClipboardFormats(UINT wFormat)
2049{
2050 CLIPBOARDINFO cbinfo;
2051 UINT wNextFormat = 0;
2052
2053 TRACE("(%04X)\n", wFormat);
2054
2055 X11DRV_CLIPBOARD_UpdateCache(&cbinfo);
2056
2057 if (!wFormat)
2058 {
2059 if (ClipData)
2060 wNextFormat = ClipData->wFormatID;
2061 }
2062 else
2063 {
2064 LPWINE_CLIPDATA lpData = X11DRV_CLIPBOARD_LookupData(wFormat);
2065
2066 if (lpData && lpData->NextData != ClipData)
2067 wNextFormat = lpData->NextData->wFormatID;
2068 }
2069
2070 return wNextFormat;
2071}
2072
2073
2074/**************************************************************************
2075 * X11DRV_IsClipboardFormatAvailable
Noel Borthwick29700671999-09-03 15:17:57 +00002076 */
Alexandre Julliard42d20f92000-08-10 01:16:19 +00002077BOOL X11DRV_IsClipboardFormatAvailable(UINT wFormat)
Noel Borthwick29700671999-09-03 15:17:57 +00002078{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002079 BOOL bRet = FALSE;
2080 CLIPBOARDINFO cbinfo;
Noel Borthwick29700671999-09-03 15:17:57 +00002081
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002082 TRACE("(%04X)\n", wFormat);
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +00002083
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002084 X11DRV_CLIPBOARD_UpdateCache(&cbinfo);
Noel Borthwick29700671999-09-03 15:17:57 +00002085
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002086 if (wFormat != 0 && X11DRV_CLIPBOARD_LookupData(wFormat))
2087 bRet = TRUE;
Noel Borthwick29700671999-09-03 15:17:57 +00002088
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002089 TRACE("(%04X)- ret(%d)\n", wFormat, bRet);
Vincent Béron9a624912002-05-31 23:06:46 +00002090
Alex Korobka44a1b591999-04-01 12:03:52 +00002091 return bRet;
Patrik Stridvalle35d6361998-12-07 09:13:40 +00002092}
2093
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002094
2095/**************************************************************************
2096 * GetClipboardData (USER.142)
2097 */
2098BOOL X11DRV_GetClipboardData(UINT wFormat, HANDLE16* phData16, HANDLE* phData32)
2099{
2100 CLIPBOARDINFO cbinfo;
2101 LPWINE_CLIPDATA lpRender;
2102
2103 TRACE("(%04X)\n", wFormat);
2104
2105 X11DRV_CLIPBOARD_UpdateCache(&cbinfo);
2106
2107 if ((lpRender = X11DRV_CLIPBOARD_LookupData(wFormat)))
2108 {
2109 if ( !lpRender->hData32 )
2110 X11DRV_CLIPBOARD_RenderFormat(lpRender);
2111
2112 /* Convert between 32 -> 16 bit data, if necessary */
2113 if (lpRender->hData32 && !lpRender->hData16)
2114 {
2115 int size;
2116
2117 if (lpRender->wFormatID == CF_METAFILEPICT)
2118 size = sizeof(METAFILEPICT16);
2119 else
2120 size = GlobalSize(lpRender->hData32);
2121
2122 lpRender->hData16 = GlobalAlloc16(GMEM_ZEROINIT, size);
2123
2124 if (!lpRender->hData16)
2125 ERR("(%04X) -- not enough memory in 16b heap\n", wFormat);
2126 else
2127 {
2128 if (lpRender->wFormatID == CF_METAFILEPICT)
2129 {
2130 FIXME("\timplement function CopyMetaFilePict32to16\n");
2131 FIXME("\tin the appropriate file.\n");
2132 #ifdef SOMEONE_IMPLEMENTED_ME
2133 CopyMetaFilePict32to16(GlobalLock16(lpRender->hData16),
2134 GlobalLock(lpRender->hData32));
2135 #endif
2136 }
2137 else
2138 {
2139 memcpy(GlobalLock16(lpRender->hData16),
2140 GlobalLock(lpRender->hData32), size);
2141 }
2142
2143 GlobalUnlock16(lpRender->hData16);
2144 GlobalUnlock(lpRender->hData32);
2145 }
2146 }
2147
2148 /* Convert between 32 -> 16 bit data, if necessary */
2149 if (lpRender->hData16 && !lpRender->hData32)
2150 {
2151 int size;
2152
2153 if (lpRender->wFormatID == CF_METAFILEPICT)
2154 size = sizeof(METAFILEPICT16);
2155 else
2156 size = GlobalSize(lpRender->hData32);
2157
2158 lpRender->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE |
2159 GMEM_DDESHARE, size);
2160
2161 if (lpRender->wFormatID == CF_METAFILEPICT)
2162 {
2163 FIXME("\timplement function CopyMetaFilePict16to32\n");
2164 FIXME("\tin the appropriate file.\n");
2165#ifdef SOMEONE_IMPLEMENTED_ME
2166 CopyMetaFilePict16to32(GlobalLock16(lpRender->hData32),
2167 GlobalLock(lpRender->hData16));
2168#endif
2169 }
2170 else
2171 {
2172 memcpy(GlobalLock(lpRender->hData32),
2173 GlobalLock16(lpRender->hData16), size);
2174 }
2175
2176 GlobalUnlock(lpRender->hData32);
2177 GlobalUnlock16(lpRender->hData16);
2178 }
2179
2180 if (phData16)
2181 *phData16 = lpRender->hData16;
2182
2183 if (phData32)
2184 *phData32 = lpRender->hData32;
2185
2186 TRACE(" returning hData16(%04x) hData32(%04x) (type %d)\n",
2187 lpRender->hData16, (unsigned int) lpRender->hData32, lpRender->wFormatID);
2188
2189 return lpRender->hData16 || lpRender->hData32;
2190 }
2191
2192 return 0;
2193}
2194
2195
Patrik Stridvalle35d6361998-12-07 09:13:40 +00002196/**************************************************************************
Patrik Stridvalldf75e892001-02-12 03:49:07 +00002197 * ResetSelectionOwner (X11DRV.@)
Patrik Stridvalle35d6361998-12-07 09:13:40 +00002198 *
Noel Borthwick29700671999-09-03 15:17:57 +00002199 * Called from DestroyWindow() to prevent X selection from being lost when
2200 * a top level window is destroyed, by switching ownership to another top
2201 * level window.
2202 * Any top level window can own the selection. See X11DRV_CLIPBOARD_Acquire
2203 * for a more detailed description of this.
Patrik Stridvalle35d6361998-12-07 09:13:40 +00002204 */
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002205void X11DRV_ResetSelectionOwner(HWND hwnd, BOOL bFooBar)
Patrik Stridvalle35d6361998-12-07 09:13:40 +00002206{
Alexandre Julliard43230042001-05-16 19:52:29 +00002207 Display *display = thread_display();
Noel Borthwick29700671999-09-03 15:17:57 +00002208 HWND hWndClipOwner = 0;
Alexandre Julliard4ff32c82001-08-18 18:08:26 +00002209 HWND tmp;
2210 Window XWnd = X11DRV_get_whole_window(hwnd);
Noel Borthwick29700671999-09-03 15:17:57 +00002211 BOOL bLostSelection = FALSE;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002212 Window selectionPrevWindow;
Patrik Stridvalle35d6361998-12-07 09:13:40 +00002213
Noel Borthwick29700671999-09-03 15:17:57 +00002214 /* There is nothing to do if we don't own the selection,
Ulrich Czekalla18873e72003-07-08 21:02:51 +00002215 * or if the X window which currently owns the selection is different
Noel Borthwick29700671999-09-03 15:17:57 +00002216 * from the one passed in.
2217 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002218 if (!selectionAcquired || XWnd != selectionWindow
Noel Borthwick29700671999-09-03 15:17:57 +00002219 || selectionWindow == None )
2220 return;
Patrik Stridvall151170c1998-12-26 12:00:43 +00002221
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002222 if ((bFooBar && XWnd) || (!bFooBar && !XWnd))
Noel Borthwick29700671999-09-03 15:17:57 +00002223 return;
Patrik Stridvall151170c1998-12-26 12:00:43 +00002224
Noel Borthwick29700671999-09-03 15:17:57 +00002225 hWndClipOwner = GetClipboardOwner();
Vincent Béron9a624912002-05-31 23:06:46 +00002226
Alexandre Julliarde0315e42002-10-31 02:38:20 +00002227 TRACE("clipboard owner = %p, selection window = %08x\n",
Noel Borthwick29700671999-09-03 15:17:57 +00002228 hWndClipOwner, (unsigned)selectionWindow);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00002229
Patrik Stridvalle35d6361998-12-07 09:13:40 +00002230 /* now try to salvage current selection from being destroyed by X */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002231 TRACE("checking %08x\n", (unsigned) XWnd);
Noel Borthwick29700671999-09-03 15:17:57 +00002232
2233 selectionPrevWindow = selectionWindow;
2234 selectionWindow = None;
2235
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002236 if (!(tmp = GetWindow(hwnd, GW_HWNDNEXT)))
2237 tmp = GetWindow(hwnd, GW_HWNDFIRST);
Noel Borthwick29700671999-09-03 15:17:57 +00002238
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002239 if (tmp && tmp != hwnd)
2240 selectionWindow = X11DRV_get_whole_window(tmp);
2241
2242 if (selectionWindow != None)
Noel Borthwick29700671999-09-03 15:17:57 +00002243 {
2244 /* We must pretend that we don't own the selection while making the switch
2245 * since a SelectionClear event will be sent to the last owner.
2246 * If there is no owner X11DRV_CLIPBOARD_ReleaseSelection will do nothing.
2247 */
2248 int saveSelectionState = selectionAcquired;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002249 selectionAcquired = S_NOSELECTION;
Noel Borthwick29700671999-09-03 15:17:57 +00002250
Vincent Béron9a624912002-05-31 23:06:46 +00002251 TRACE("\tswitching selection from %08x to %08x\n",
Noel Borthwick29700671999-09-03 15:17:57 +00002252 (unsigned)selectionPrevWindow, (unsigned)selectionWindow);
Vincent Béron9a624912002-05-31 23:06:46 +00002253
Noel Borthwick29700671999-09-03 15:17:57 +00002254 /* Assume ownership for the PRIMARY and CLIPBOARD selection */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002255 if (saveSelectionState & S_PRIMARY)
Noel Borthwick29700671999-09-03 15:17:57 +00002256 TSXSetSelectionOwner(display, XA_PRIMARY, selectionWindow, CurrentTime);
Vincent Béron9a624912002-05-31 23:06:46 +00002257
Alexandre Julliardd09c3282003-11-20 04:24:18 +00002258 TSXSetSelectionOwner(display, x11drv_atom(CLIPBOARD), selectionWindow, CurrentTime);
Francis Beaudet56ab55d1999-10-24 20:22:24 +00002259
2260 /* Restore the selection masks */
2261 selectionAcquired = saveSelectionState;
2262
Noel Borthwick29700671999-09-03 15:17:57 +00002263 /* Lose the selection if something went wrong */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002264 if (((saveSelectionState & S_PRIMARY) &&
2265 (TSXGetSelectionOwner(display, XA_PRIMARY) != selectionWindow)) ||
Alexandre Julliardd09c3282003-11-20 04:24:18 +00002266 (TSXGetSelectionOwner(display, x11drv_atom(CLIPBOARD)) != selectionWindow))
Noel Borthwick29700671999-09-03 15:17:57 +00002267 {
2268 bLostSelection = TRUE;
Noel Borthwick29700671999-09-03 15:17:57 +00002269 }
2270 else
2271 {
2272 /* Update selection state */
Noel Borthwick29700671999-09-03 15:17:57 +00002273 if (saveSelectionState & S_PRIMARY)
2274 PrimarySelectionOwner = selectionWindow;
Vincent Béron9a624912002-05-31 23:06:46 +00002275
Noel Borthwick29700671999-09-03 15:17:57 +00002276 ClipboardSelectionOwner = selectionWindow;
2277 }
2278 }
2279 else
2280 {
2281 bLostSelection = TRUE;
Noel Borthwick29700671999-09-03 15:17:57 +00002282 }
2283
Noel Borthwick29700671999-09-03 15:17:57 +00002284 if (bLostSelection)
2285 {
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002286 TRACE("Lost the selection!\n");
Vincent Béron9a624912002-05-31 23:06:46 +00002287
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002288 X11DRV_CLIPBOARD_ReleaseOwnership();
2289 selectionAcquired = S_NOSELECTION;
2290 ClipboardSelectionOwner = PrimarySelectionOwner = 0;
2291 selectionWindow = 0;
Noel Borthwick29700671999-09-03 15:17:57 +00002292 }
Patrik Stridvalle35d6361998-12-07 09:13:40 +00002293}
2294
Ulrich Czekalla651c5982002-08-27 19:19:49 +00002295
2296/**************************************************************************
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002297 * X11DRV_CLIPBOARD_SynthesizeData
Ulrich Czekalla651c5982002-08-27 19:19:49 +00002298 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002299static BOOL X11DRV_CLIPBOARD_SynthesizeData(UINT wFormatID)
Ulrich Czekalla651c5982002-08-27 19:19:49 +00002300{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002301 BOOL bsyn = TRUE;
2302 LPWINE_CLIPDATA lpSource = NULL;
Ulrich Czekalla651c5982002-08-27 19:19:49 +00002303
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002304 TRACE(" %d\n", wFormatID);
2305
2306 /* Don't need to synthesize if it already exists */
2307 if (X11DRV_CLIPBOARD_LookupData(wFormatID))
2308 return TRUE;
2309
2310 if (wFormatID == CF_UNICODETEXT || wFormatID == CF_TEXT || wFormatID == CF_OEMTEXT)
Ulrich Czekalla651c5982002-08-27 19:19:49 +00002311 {
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002312 bsyn = ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_UNICODETEXT)) &&
2313 ~lpSource->wFlags & CF_FLAG_SYNTHESIZED) ||
2314 ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_TEXT)) &&
2315 ~lpSource->wFlags & CF_FLAG_SYNTHESIZED) ||
2316 ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_OEMTEXT)) &&
2317 ~lpSource->wFlags & CF_FLAG_SYNTHESIZED);
Ulrich Czekalla651c5982002-08-27 19:19:49 +00002318 }
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002319 else if (wFormatID == CF_ENHMETAFILE)
Ulrich Czekalla651c5982002-08-27 19:19:49 +00002320 {
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002321 bsyn = (lpSource = X11DRV_CLIPBOARD_LookupData(CF_METAFILEPICT)) &&
2322 ~lpSource->wFlags & CF_FLAG_SYNTHESIZED;
2323 }
2324 else if (wFormatID == CF_METAFILEPICT)
2325 {
2326 bsyn = (lpSource = X11DRV_CLIPBOARD_LookupData(CF_METAFILEPICT)) &&
2327 ~lpSource->wFlags & CF_FLAG_SYNTHESIZED;
2328 }
2329 else if (wFormatID == CF_DIB)
2330 {
2331 bsyn = (lpSource = X11DRV_CLIPBOARD_LookupData(CF_BITMAP)) &&
2332 ~lpSource->wFlags & CF_FLAG_SYNTHESIZED;
2333 }
2334 else if (wFormatID == CF_BITMAP)
2335 {
2336 bsyn = (lpSource = X11DRV_CLIPBOARD_LookupData(CF_DIB)) &&
2337 ~lpSource->wFlags & CF_FLAG_SYNTHESIZED;
Ulrich Czekalla651c5982002-08-27 19:19:49 +00002338 }
2339
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00002340 if (bsyn)
2341 X11DRV_CLIPBOARD_InsertClipboardData(wFormatID, 0, 0, CF_FLAG_SYNTHESIZED);
2342
2343 return bsyn;
2344}
2345
2346
2347
2348/**************************************************************************
2349 * X11DRV_EndClipboardUpdate
2350 * TODO:
2351 * Add locale if it hasn't already been added
2352 */
2353void X11DRV_EndClipboardUpdate(void)
2354{
2355 INT count = ClipDataCount;
2356
2357 /* Do Unicode <-> Text <-> OEM mapping */
2358 X11DRV_CLIPBOARD_SynthesizeData(CF_UNICODETEXT);
2359 X11DRV_CLIPBOARD_SynthesizeData(CF_TEXT);
2360 X11DRV_CLIPBOARD_SynthesizeData(CF_OEMTEXT);
2361
2362 /* Enhmetafile <-> MetafilePict mapping */
2363 X11DRV_CLIPBOARD_SynthesizeData(CF_ENHMETAFILE);
2364 X11DRV_CLIPBOARD_SynthesizeData(CF_METAFILEPICT);
2365
2366 /* DIB <-> Bitmap mapping */
2367 X11DRV_CLIPBOARD_SynthesizeData(CF_DIB);
2368 X11DRV_CLIPBOARD_SynthesizeData(CF_BITMAP);
2369
2370 TRACE("%d formats added to cached data\n", ClipDataCount - count);
Ulrich Czekalla651c5982002-08-27 19:19:49 +00002371}