rpcrt4: Add tests for a complex array of pointers.
[wine] / dlls / winex11.drv / clipboard.c
1 /*
2  * X11 clipboard windows driver
3  *
4  * Copyright 1994 Martin Ayotte
5  *           1996 Alex Korobka
6  *           1999 Noel Borthwick
7  *           2003 Ulrich Czekalla for CodeWeavers
8  *
9  * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  *
23  * 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  *
33  *    In our implementation, the CLIPBOARD selection takes precedence over PRIMARY,
34  *    i.e. if a CLIPBOARD selection is available, it is used instead of PRIMARY.
35  *    When Wine takes ownership of the clipboard, it takes ownership of BOTH selections.
36  *    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,
44  *    or when a built-in format is used for the first time.
45  *    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
52  *    availability of a particular format, by caching the list of available targets
53  *    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  *
61  * FIXME: global format list needs a critical section
62  */
63
64 #include "config.h"
65 #include "wine/port.h"
66
67 #include <string.h>
68 #include <stdarg.h>
69 #include <stdio.h>
70 #include <stdlib.h>
71 #ifdef HAVE_UNISTD_H
72 # include <unistd.h>
73 #endif
74 #include <fcntl.h>
75 #include <limits.h>
76 #include <time.h>
77 #include <assert.h>
78
79 #include "windef.h"
80 #include "winbase.h"
81 #include "x11drv.h"
82 #include "wine/debug.h"
83 #include "wine/unicode.h"
84 #include "wine/server.h"
85
86 WINE_DEFAULT_DEBUG_CHANNEL(clipboard);
87
88 /* Maximum wait time for selection notify */
89 #define SELECTION_RETRIES 500  /* wait for .1 seconds */
90 #define SELECTION_WAIT    1000 /* us */
91 /* Minimum seconds that must lapse between owner queries */
92 #define OWNERQUERYLAPSETIME 1
93
94 /* Selection masks */
95 #define S_NOSELECTION    0
96 #define S_PRIMARY        1
97 #define S_CLIPBOARD      2
98
99 typedef struct
100 {
101     HWND hWndOpen;
102     HWND hWndOwner;
103     HWND hWndViewer;
104     UINT seqno;
105     UINT flags;
106 } CLIPBOARDINFO, *LPCLIPBOARDINFO;
107
108 struct tagWINE_CLIPDATA; /* Forward */
109
110 typedef HANDLE (*DRVEXPORTFUNC)(Display *display, Window requestor, Atom aTarget, Atom rprop,
111     struct tagWINE_CLIPDATA* lpData, LPDWORD lpBytes);
112 typedef HANDLE (*DRVIMPORTFUNC)(Display *d, Window w, Atom prop);
113
114 typedef struct tagWINE_CLIPFORMAT {
115     UINT        wFormatID;
116     LPCWSTR     Name;
117     UINT        drvData;
118     UINT        wFlags;
119     DRVIMPORTFUNC  lpDrvImportFunc;
120     DRVEXPORTFUNC  lpDrvExportFunc;
121     struct tagWINE_CLIPFORMAT *PrevFormat;
122     struct tagWINE_CLIPFORMAT *NextFormat;
123 } WINE_CLIPFORMAT, *LPWINE_CLIPFORMAT;
124
125 typedef struct tagWINE_CLIPDATA {
126     UINT        wFormatID;
127     HANDLE      hData;
128     UINT        wFlags;
129     UINT        drvData;
130     LPWINE_CLIPFORMAT lpFormat;
131     struct tagWINE_CLIPDATA *PrevData;
132     struct tagWINE_CLIPDATA *NextData;
133 } WINE_CLIPDATA, *LPWINE_CLIPDATA;
134
135 #define CF_FLAG_BUILTINFMT   0x0001 /* Built-in windows format */
136 #define CF_FLAG_UNOWNED      0x0002 /* cached data is not owned */
137 #define CF_FLAG_SYNTHESIZED  0x0004 /* Implicitly converted data */
138 #define CF_FLAG_UNICODE      0x0008 /* Data is in unicode */
139
140 static int selectionAcquired = 0;              /* Contains the current selection masks */
141 static Window selectionWindow = None;          /* The top level X window which owns the selection */
142 static Atom selectionCacheSrc = XA_PRIMARY;    /* The selection source from which the clipboard cache was filled */
143
144 void CDECL X11DRV_EmptyClipboard(BOOL keepunowned);
145 void CDECL X11DRV_EndClipboardUpdate(void);
146 static HANDLE X11DRV_CLIPBOARD_ImportClipboardData(Display *d, Window w, Atom prop);
147 static HANDLE X11DRV_CLIPBOARD_ImportEnhMetaFile(Display *d, Window w, Atom prop);
148 static HANDLE X11DRV_CLIPBOARD_ImportMetaFilePict(Display *d, Window w, Atom prop);
149 static HANDLE X11DRV_CLIPBOARD_ImportXAPIXMAP(Display *d, Window w, Atom prop);
150 static HANDLE X11DRV_CLIPBOARD_ImportImageBmp(Display *d, Window w, Atom prop);
151 static HANDLE X11DRV_CLIPBOARD_ImportXAString(Display *d, Window w, Atom prop);
152 static HANDLE X11DRV_CLIPBOARD_ImportUTF8(Display *d, Window w, Atom prop);
153 static HANDLE X11DRV_CLIPBOARD_ImportCompoundText(Display *d, Window w, Atom prop);
154 static HANDLE X11DRV_CLIPBOARD_ExportClipboardData(Display *display, Window requestor, Atom aTarget,
155     Atom rprop, LPWINE_CLIPDATA lpData, LPDWORD lpBytes);
156 static HANDLE X11DRV_CLIPBOARD_ExportString(Display *display, Window requestor, Atom aTarget,
157     Atom rprop, LPWINE_CLIPDATA lpData, LPDWORD lpBytes);
158 static HANDLE X11DRV_CLIPBOARD_ExportXAPIXMAP(Display *display, Window requestor, Atom aTarget,
159     Atom rprop, LPWINE_CLIPDATA lpdata, LPDWORD lpBytes);
160 static HANDLE X11DRV_CLIPBOARD_ExportImageBmp(Display *display, Window requestor, Atom aTarget,
161     Atom rprop, LPWINE_CLIPDATA lpdata, LPDWORD lpBytes);
162 static HANDLE X11DRV_CLIPBOARD_ExportMetaFilePict(Display *display, Window requestor, Atom aTarget,
163     Atom rprop, LPWINE_CLIPDATA lpdata, LPDWORD lpBytes);
164 static HANDLE X11DRV_CLIPBOARD_ExportEnhMetaFile(Display *display, Window requestor, Atom aTarget,
165     Atom rprop, LPWINE_CLIPDATA lpdata, LPDWORD lpBytes);
166 static HANDLE X11DRV_CLIPBOARD_ExportTextHtml(Display *display, Window requestor, Atom aTarget,
167     Atom rprop, LPWINE_CLIPDATA lpdata, LPDWORD lpBytes);
168 static WINE_CLIPFORMAT *X11DRV_CLIPBOARD_InsertClipboardFormat(LPCWSTR FormatName, Atom prop);
169 static BOOL X11DRV_CLIPBOARD_RenderSynthesizedText(Display *display, UINT wFormatID);
170 static void X11DRV_CLIPBOARD_FreeData(LPWINE_CLIPDATA lpData);
171 static BOOL X11DRV_CLIPBOARD_IsSelectionOwner(void);
172 static int X11DRV_CLIPBOARD_QueryAvailableData(Display *display, LPCLIPBOARDINFO lpcbinfo);
173 static BOOL X11DRV_CLIPBOARD_ReadSelectionData(Display *display, LPWINE_CLIPDATA lpData);
174 static BOOL X11DRV_CLIPBOARD_ReadProperty(Display *display, Window w, Atom prop,
175     unsigned char** data, unsigned long* datasize);
176 static BOOL X11DRV_CLIPBOARD_RenderFormat(Display *display, LPWINE_CLIPDATA lpData);
177 static HANDLE X11DRV_CLIPBOARD_SerializeMetafile(INT wformat, HANDLE hdata, LPDWORD lpcbytes, BOOL out);
178 static BOOL X11DRV_CLIPBOARD_SynthesizeData(UINT wFormatID);
179 static BOOL X11DRV_CLIPBOARD_RenderSynthesizedFormat(Display *display, LPWINE_CLIPDATA lpData);
180 static BOOL X11DRV_CLIPBOARD_RenderSynthesizedDIB(Display *display);
181 static BOOL X11DRV_CLIPBOARD_RenderSynthesizedBitmap(Display *display);
182 static void X11DRV_HandleSelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple );
183
184 /* Clipboard formats
185  * WARNING: This data ordering is dependent on the WINE_CLIPFORMAT structure
186  * declared in clipboard.h
187  */
188 static const WCHAR wszCF_TEXT[] = {'W','C','F','_','T','E','X','T',0};
189 static const WCHAR wszCF_BITMAP[] = {'W','C','F','_','B','I','T','M','A','P',0};
190 static const WCHAR wszCF_METAFILEPICT[] = {'W','C','F','_','M','E','T','A','F','I','L','E','P','I','C','T',0};
191 static const WCHAR wszCF_SYLK[] = {'W','C','F','_','S','Y','L','K',0};
192 static const WCHAR wszCF_DIF[] = {'W','C','F','_','D','I','F',0};
193 static const WCHAR wszCF_TIFF[] = {'W','C','F','_','T','I','F','F',0};
194 static const WCHAR wszCF_OEMTEXT[] = {'W','C','F','_','O','E','M','T','E','X','T',0};
195 static const WCHAR wszCF_DIB[] = {'W','C','F','_','D','I','B',0};
196 static const WCHAR wszIMAGEBMP[] = {'i','m','a','g','e','/','b','m','p',0};
197 static const WCHAR wszCF_PALETTE[] = {'W','C','F','_','P','A','L','E','T','T','E',0};
198 static const WCHAR wszCF_PENDATA[] = {'W','C','F','_','P','E','N','D','A','T','A',0};
199 static const WCHAR wszCF_RIFF[] = {'W','C','F','_','R','I','F','F',0};
200 static const WCHAR wszCF_WAVE[] = {'W','C','F','_','W','A','V','E',0};
201 static const WCHAR wszCOMPOUNDTEXT[] = {'C','O','M','P','O','U','N','D','_','T','E','X','T',0};
202 static const WCHAR wszUTF8STRING[] = {'U','T','F','8','_','S','T','R','I','N','G',0};
203 static const WCHAR wszCF_ENHMETAFILE[] = {'W','C','F','_','E','N','H','M','E','T','A','F','I','L','E',0};
204 static const WCHAR wszCF_HDROP[] = {'W','C','F','_','H','D','R','O','P',0};
205 static const WCHAR wszCF_LOCALE[] = {'W','C','F','_','L','O','C','A','L','E',0};
206 static const WCHAR wszCF_DIBV5[] = {'W','C','F','_','D','I','B','V','5',0};
207 static const WCHAR wszCF_OWNERDISPLAY[] = {'W','C','F','_','O','W','N','E','R','D','I','S','P','L','A','Y',0};
208 static const WCHAR wszCF_DSPTEXT[] = {'W','C','F','_','D','S','P','T','E','X','T',0};
209 static const WCHAR wszCF_DSPBITMAP[] = {'W','C','F','_','D','S','P','B','I','T','M','A','P',0};
210 static const WCHAR wszCF_DSPMETAFILEPICT[] = {'W','C','F','_','D','S','P','M','E','T','A','F','I','L','E','P','I','C','T',0};
211 static const WCHAR wszCF_DSPENHMETAFILE[] = {'W','C','F','_','D','S','P','E','N','H','M','E','T','A','F','I','L','E',0};
212
213 static WINE_CLIPFORMAT ClipFormats[]  =
214 {
215     { CF_TEXT, wszCF_TEXT, XA_STRING, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportXAString,
216         X11DRV_CLIPBOARD_ExportString, NULL, &ClipFormats[1]},
217
218     { CF_BITMAP, wszCF_BITMAP, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
219         NULL, &ClipFormats[0], &ClipFormats[2]},
220
221     { CF_METAFILEPICT, wszCF_METAFILEPICT, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportMetaFilePict,
222         X11DRV_CLIPBOARD_ExportMetaFilePict, &ClipFormats[1], &ClipFormats[3]},
223
224     { CF_SYLK, wszCF_SYLK, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
225         X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[2], &ClipFormats[4]},
226
227     { CF_DIF, wszCF_DIF, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
228         X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[3], &ClipFormats[5]},
229
230     { CF_TIFF, wszCF_TIFF, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
231         X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[4], &ClipFormats[6]},
232
233     { CF_OEMTEXT, wszCF_OEMTEXT, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
234         X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[5], &ClipFormats[7]},
235
236     { CF_DIB, wszCF_DIB, XA_PIXMAP, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportXAPIXMAP,
237         X11DRV_CLIPBOARD_ExportXAPIXMAP, &ClipFormats[6], &ClipFormats[8]},
238
239     { CF_PALETTE, wszCF_PALETTE, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
240         X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[7], &ClipFormats[9]},
241
242     { CF_PENDATA, wszCF_PENDATA, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
243         X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[8], &ClipFormats[10]},
244
245     { CF_RIFF, wszCF_RIFF, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
246         X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[9], &ClipFormats[11]},
247
248     { CF_WAVE, wszCF_WAVE, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
249         X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[10], &ClipFormats[12]},
250
251     { CF_UNICODETEXT, wszUTF8STRING, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportUTF8,
252         X11DRV_CLIPBOARD_ExportString, &ClipFormats[11], &ClipFormats[13]},
253
254     /* If UTF8_STRING is not available, attempt COMPUND_TEXT */
255     { CF_UNICODETEXT, wszCOMPOUNDTEXT, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportCompoundText,
256         X11DRV_CLIPBOARD_ExportString, &ClipFormats[12], &ClipFormats[14]},
257
258     { CF_ENHMETAFILE, wszCF_ENHMETAFILE, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportEnhMetaFile,
259         X11DRV_CLIPBOARD_ExportEnhMetaFile, &ClipFormats[13], &ClipFormats[15]},
260
261     { CF_HDROP, wszCF_HDROP, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
262         X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[14], &ClipFormats[16]},
263
264     { CF_LOCALE, wszCF_LOCALE, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
265         X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[15], &ClipFormats[17]},
266
267     { CF_DIBV5, wszCF_DIBV5, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
268         X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[16], &ClipFormats[18]},
269
270     { CF_OWNERDISPLAY, wszCF_OWNERDISPLAY, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
271         X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[17], &ClipFormats[19]},
272
273     { CF_DSPTEXT, wszCF_DSPTEXT, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
274         X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[18], &ClipFormats[20]},
275
276     { CF_DSPBITMAP, wszCF_DSPBITMAP, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
277         X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[19], &ClipFormats[21]},
278
279     { CF_DSPMETAFILEPICT, wszCF_DSPMETAFILEPICT, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
280         X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[20], &ClipFormats[22]},
281
282     { CF_DSPENHMETAFILE, wszCF_DSPENHMETAFILE, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
283         X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[21], &ClipFormats[23]},
284
285     { CF_DIB, wszIMAGEBMP, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportImageBmp,
286         X11DRV_CLIPBOARD_ExportImageBmp, &ClipFormats[22], NULL},
287 };
288
289 #define GET_ATOM(prop)  (((prop) < FIRST_XATOM) ? (Atom)(prop) : X11DRV_Atoms[(prop) - FIRST_XATOM])
290
291 /* Maps X properties to Windows formats */
292 static const WCHAR wszRichTextFormat[] = {'R','i','c','h',' ','T','e','x','t',' ','F','o','r','m','a','t',0};
293 static const WCHAR wszGIF[] = {'G','I','F',0};
294 static const WCHAR wszJFIF[] = {'J','F','I','F',0};
295 static const WCHAR wszPNG[] = {'P','N','G',0};
296 static const WCHAR wszHTMLFormat[] = {'H','T','M','L',' ','F','o','r','m','a','t',0};
297 static const struct
298 {
299     LPCWSTR lpszFormat;
300     UINT   prop;
301 } PropertyFormatMap[] =
302 {
303     { wszRichTextFormat, XATOM_text_rtf },
304     { wszRichTextFormat, XATOM_text_richtext },
305     { wszGIF, XATOM_image_gif },
306     { wszJFIF, XATOM_image_jpeg },
307     { wszPNG, XATOM_image_png },
308     { wszHTMLFormat, XATOM_HTML_Format }, /* prefer this to text/html */
309 };
310
311
312 /*
313  * Cached clipboard data.
314  */
315 static LPWINE_CLIPDATA ClipData = NULL;
316 static UINT ClipDataCount = 0;
317
318 /*
319  * Clipboard sequence number
320  */
321 static UINT wSeqNo = 0;
322
323 /**************************************************************************
324  *                Internal Clipboard implementation methods
325  **************************************************************************/
326
327 static Window thread_selection_wnd(void)
328 {
329     struct x11drv_thread_data *thread_data = x11drv_init_thread_data();
330     Window w = thread_data->selection_wnd;
331
332     if (!w)
333     {
334         XSetWindowAttributes attr;
335
336         attr.event_mask = (ExposureMask | KeyPressMask | KeyReleaseMask | PointerMotionMask |
337                        ButtonPressMask | ButtonReleaseMask | EnterWindowMask | PropertyChangeMask);
338
339         wine_tsx11_lock();
340         w = XCreateWindow(thread_data->display, root_window, 0, 0, 1, 1, 0, screen_depth,
341                           InputOutput, CopyFromParent, CWEventMask, &attr);
342         wine_tsx11_unlock();
343
344         if (w)
345             thread_data->selection_wnd = w;
346         else
347             FIXME("Failed to create window. Fetching selection data will fail.\n");
348     }
349
350     return w;
351 }
352
353 /**************************************************************************
354  *              X11DRV_InitClipboard
355  */
356 void X11DRV_InitClipboard(void)
357 {
358     UINT i;
359     WINE_CLIPFORMAT *format;
360
361     /* Register known mapping between window formats and X properties */
362     for (i = 0; i < sizeof(PropertyFormatMap)/sizeof(PropertyFormatMap[0]); i++)
363         X11DRV_CLIPBOARD_InsertClipboardFormat(PropertyFormatMap[i].lpszFormat, GET_ATOM(PropertyFormatMap[i].prop));
364
365     /* Set up a conversion function from "HTML Format" to "text/html" */
366     format = X11DRV_CLIPBOARD_InsertClipboardFormat(wszHTMLFormat, GET_ATOM(XATOM_text_html));
367     format->lpDrvExportFunc = X11DRV_CLIPBOARD_ExportTextHtml;
368 }
369
370
371 /**************************************************************************
372  *                intern_atoms
373  *
374  * Intern atoms for formats that don't have one yet.
375  */
376 static void intern_atoms(void)
377 {
378     LPWINE_CLIPFORMAT format;
379     int i, count, len;
380     char **names;
381     Atom *atoms;
382     Display *display;
383
384     for (format = ClipFormats, count = 0; format; format = format->NextFormat)
385         if (!format->drvData) count++;
386     if (!count) return;
387
388     display = thread_init_display();
389
390     names = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*names) );
391     atoms = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*atoms) );
392
393     for (format = ClipFormats, i = 0; format; format = format->NextFormat) {
394         if (!format->drvData) {
395             len = WideCharToMultiByte(CP_UNIXCP, 0, format->Name, -1, NULL, 0, NULL, NULL);
396             names[i] = HeapAlloc(GetProcessHeap(), 0, len);
397             WideCharToMultiByte(CP_UNIXCP, 0, format->Name, -1, names[i++], len, NULL, NULL);
398         }
399     }
400
401     wine_tsx11_lock();
402     XInternAtoms( display, names, count, False, atoms );
403     wine_tsx11_unlock();
404
405     for (format = ClipFormats, i = 0; format; format = format->NextFormat) {
406         if (!format->drvData) {
407             HeapFree(GetProcessHeap(), 0, names[i]);
408             format->drvData = atoms[i++];
409         }
410     }
411
412     HeapFree( GetProcessHeap(), 0, names );
413     HeapFree( GetProcessHeap(), 0, atoms );
414 }
415
416
417 /**************************************************************************
418  *              register_format
419  *
420  * Register a custom X clipboard format.
421  */
422 static WINE_CLIPFORMAT *register_format( LPCWSTR FormatName, Atom prop )
423 {
424     LPWINE_CLIPFORMAT lpFormat = ClipFormats;
425
426     TRACE("%s\n", debugstr_w(FormatName));
427
428     /* walk format chain to see if it's already registered */
429     while (lpFormat)
430     {
431         if (CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, lpFormat->Name, -1, FormatName, -1) == CSTR_EQUAL
432             && (lpFormat->wFlags & CF_FLAG_BUILTINFMT) == 0)
433              return lpFormat;
434         lpFormat = lpFormat->NextFormat;
435     }
436
437     return X11DRV_CLIPBOARD_InsertClipboardFormat(FormatName, prop);
438 }
439
440
441 /**************************************************************************
442  *                X11DRV_CLIPBOARD_LookupFormat
443  */
444 static LPWINE_CLIPFORMAT X11DRV_CLIPBOARD_LookupFormat(WORD wID)
445 {
446     LPWINE_CLIPFORMAT lpFormat = ClipFormats;
447
448     while(lpFormat)
449     {
450         if (lpFormat->wFormatID == wID) 
451             break;
452
453         lpFormat = lpFormat->NextFormat;
454     }
455     if (lpFormat && !lpFormat->drvData) intern_atoms();
456     return lpFormat;
457 }
458
459
460 /**************************************************************************
461  *                X11DRV_CLIPBOARD_LookupProperty
462  */
463 static LPWINE_CLIPFORMAT X11DRV_CLIPBOARD_LookupProperty(LPWINE_CLIPFORMAT current, UINT drvData)
464 {
465     for (;;)
466     {
467         LPWINE_CLIPFORMAT lpFormat = ClipFormats;
468         BOOL need_intern = FALSE;
469
470         if (current)
471             lpFormat = current->NextFormat;
472
473         while(lpFormat)
474         {
475             if (lpFormat->drvData == drvData) return lpFormat;
476             if (!lpFormat->drvData) need_intern = TRUE;
477             lpFormat = lpFormat->NextFormat;
478         }
479         if (!need_intern) return NULL;
480         intern_atoms();
481         /* restart the search for the new atoms */
482     }
483 }
484
485
486 /**************************************************************************
487  *               X11DRV_CLIPBOARD_LookupData
488  */
489 static LPWINE_CLIPDATA X11DRV_CLIPBOARD_LookupData(DWORD wID)
490 {
491     LPWINE_CLIPDATA lpData = ClipData;
492
493     if (lpData)
494     {
495         do
496         {
497             if (lpData->wFormatID == wID) 
498                 break;
499
500             lpData = lpData->NextData;
501         }
502         while(lpData != ClipData);
503
504         if (lpData->wFormatID != wID)
505             lpData = NULL;
506     }
507
508     return lpData;
509 }
510
511
512 /**************************************************************************
513  *              InsertClipboardFormat
514  */
515 static WINE_CLIPFORMAT *X11DRV_CLIPBOARD_InsertClipboardFormat(LPCWSTR FormatName, Atom prop)
516 {
517     LPWINE_CLIPFORMAT lpFormat;
518     LPWINE_CLIPFORMAT lpNewFormat;
519     LPWSTR new_name;
520
521     /* allocate storage for new format entry */
522     lpNewFormat = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_CLIPFORMAT));
523
524     if(lpNewFormat == NULL) 
525     {
526         WARN("No more memory for a new format!\n");
527         return NULL;
528     }
529
530     if (!(new_name = HeapAlloc(GetProcessHeap(), 0, (strlenW(FormatName)+1)*sizeof(WCHAR))))
531     {
532         WARN("No more memory for the new format name!\n");
533         HeapFree(GetProcessHeap(), 0, lpNewFormat);
534         return NULL;
535     }
536
537     lpNewFormat->Name = strcpyW(new_name, FormatName);
538     lpNewFormat->wFlags = 0;
539     lpNewFormat->wFormatID = GlobalAddAtomW(lpNewFormat->Name);
540     lpNewFormat->drvData = prop;
541     lpNewFormat->lpDrvImportFunc = X11DRV_CLIPBOARD_ImportClipboardData;
542     lpNewFormat->lpDrvExportFunc = X11DRV_CLIPBOARD_ExportClipboardData;
543
544     /* Link Format */
545     lpFormat = ClipFormats;
546
547     while(lpFormat->NextFormat) /* Move to last entry */
548         lpFormat = lpFormat->NextFormat;
549
550     lpNewFormat->NextFormat = NULL;
551     lpFormat->NextFormat = lpNewFormat;
552     lpNewFormat->PrevFormat = lpFormat;
553
554     TRACE("Registering format(%04x): %s drvData %d\n",
555         lpNewFormat->wFormatID, debugstr_w(FormatName), lpNewFormat->drvData);
556
557     return lpNewFormat;
558 }
559
560
561
562
563 /**************************************************************************
564  *                      X11DRV_CLIPBOARD_GetClipboardInfo
565  */
566 static BOOL X11DRV_CLIPBOARD_GetClipboardInfo(LPCLIPBOARDINFO cbInfo)
567 {
568     BOOL bRet = FALSE;
569
570     SERVER_START_REQ( set_clipboard_info )
571     {
572         req->flags = 0;
573
574         if (wine_server_call_err( req ))
575         {
576             ERR("Failed to get clipboard owner.\n");
577         }
578         else
579         {
580             cbInfo->hWndOpen = wine_server_ptr_handle( reply->old_clipboard );
581             cbInfo->hWndOwner = wine_server_ptr_handle( reply->old_owner );
582             cbInfo->hWndViewer = wine_server_ptr_handle( reply->old_viewer );
583             cbInfo->seqno = reply->seqno;
584             cbInfo->flags = reply->flags;
585
586             bRet = TRUE;
587         }
588     }
589     SERVER_END_REQ;
590
591     return bRet;
592 }
593
594
595 /**************************************************************************
596  *      X11DRV_CLIPBOARD_ReleaseOwnership
597  */
598 static BOOL X11DRV_CLIPBOARD_ReleaseOwnership(void)
599 {
600     BOOL bRet = FALSE;
601
602     SERVER_START_REQ( set_clipboard_info )
603     {
604         req->flags = SET_CB_RELOWNER | SET_CB_SEQNO;
605
606         if (wine_server_call_err( req ))
607         {
608             ERR("Failed to set clipboard.\n");
609         }
610         else
611         {
612             bRet = TRUE;
613         }
614     }
615     SERVER_END_REQ;
616
617     return bRet;
618 }
619
620
621
622 /**************************************************************************
623  *                      X11DRV_CLIPBOARD_InsertClipboardData
624  *
625  * Caller *must* have the clipboard open and be the owner.
626  */
627 static BOOL X11DRV_CLIPBOARD_InsertClipboardData(UINT wFormatID, HANDLE hData, DWORD flags,
628                                                  LPWINE_CLIPFORMAT lpFormat, BOOL override)
629 {
630     LPWINE_CLIPDATA lpData = X11DRV_CLIPBOARD_LookupData(wFormatID);
631
632     TRACE("format=%04x lpData=%p hData=%p flags=0x%08x lpFormat=%p override=%d\n",
633         wFormatID, lpData, hData, flags, lpFormat, override);
634
635     if (lpData && !override)
636         return TRUE;
637
638     if (lpData)
639     {
640         X11DRV_CLIPBOARD_FreeData(lpData);
641
642         lpData->hData = hData;
643     }
644     else
645     {
646         lpData = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_CLIPDATA));
647
648         lpData->wFormatID = wFormatID;
649         lpData->hData = hData;
650         lpData->lpFormat = lpFormat;
651         lpData->drvData = 0;
652
653         if (ClipData)
654         {
655             LPWINE_CLIPDATA lpPrevData = ClipData->PrevData;
656
657             lpData->PrevData = lpPrevData;
658             lpData->NextData = ClipData;
659
660             lpPrevData->NextData = lpData;
661             ClipData->PrevData = lpData;
662         }
663         else
664         {
665             lpData->NextData = lpData;
666             lpData->PrevData = lpData;
667             ClipData = lpData;
668         }
669
670         ClipDataCount++;
671     }
672
673     lpData->wFlags = flags;
674
675     return TRUE;
676 }
677
678
679 /**************************************************************************
680  *                      X11DRV_CLIPBOARD_FreeData
681  *
682  * Free clipboard data handle.
683  */
684 static void X11DRV_CLIPBOARD_FreeData(LPWINE_CLIPDATA lpData)
685 {
686     TRACE("%04x\n", lpData->wFormatID);
687
688     if ((lpData->wFormatID >= CF_GDIOBJFIRST &&
689         lpData->wFormatID <= CF_GDIOBJLAST) || 
690         lpData->wFormatID == CF_BITMAP || 
691         lpData->wFormatID == CF_DIB || 
692         lpData->wFormatID == CF_PALETTE)
693     {
694       if (lpData->hData)
695         DeleteObject(lpData->hData);
696
697       if ((lpData->wFormatID == CF_DIB) && lpData->drvData)
698           XFreePixmap(gdi_display, lpData->drvData);
699     }
700     else if (lpData->wFormatID == CF_METAFILEPICT)
701     {
702       if (lpData->hData)
703       {
704         DeleteMetaFile(((METAFILEPICT *)GlobalLock( lpData->hData ))->hMF );
705         GlobalFree(lpData->hData);
706       }
707     }
708     else if (lpData->wFormatID == CF_ENHMETAFILE)
709     {
710         if (lpData->hData)
711             DeleteEnhMetaFile(lpData->hData);
712     }
713     else if (lpData->wFormatID < CF_PRIVATEFIRST ||
714              lpData->wFormatID > CF_PRIVATELAST)
715     {
716       if (lpData->hData)
717         GlobalFree(lpData->hData);
718     }
719
720     lpData->hData = 0;
721     lpData->drvData = 0;
722 }
723
724
725 /**************************************************************************
726  *                      X11DRV_CLIPBOARD_UpdateCache
727  */
728 static BOOL X11DRV_CLIPBOARD_UpdateCache(LPCLIPBOARDINFO lpcbinfo)
729 {
730     BOOL bret = TRUE;
731
732     if (!X11DRV_CLIPBOARD_IsSelectionOwner())
733     {
734         if (!X11DRV_CLIPBOARD_GetClipboardInfo(lpcbinfo))
735         {
736             ERR("Failed to retrieve clipboard information.\n");
737             bret = FALSE;
738         }
739         else if (wSeqNo < lpcbinfo->seqno)
740         {
741             X11DRV_EmptyClipboard(TRUE);
742
743             if (X11DRV_CLIPBOARD_QueryAvailableData(thread_init_display(), lpcbinfo) < 0)
744             {
745                 ERR("Failed to cache clipboard data owned by another process.\n");
746                 bret = FALSE;
747             }
748             else
749             {
750                 X11DRV_EndClipboardUpdate();
751             }
752
753             wSeqNo = lpcbinfo->seqno;
754         }
755     }
756
757     return bret;
758 }
759
760
761 /**************************************************************************
762  *                      X11DRV_CLIPBOARD_RenderFormat
763  */
764 static BOOL X11DRV_CLIPBOARD_RenderFormat(Display *display, LPWINE_CLIPDATA lpData)
765 {
766     BOOL bret = TRUE;
767
768     TRACE(" 0x%04x hData(%p)\n", lpData->wFormatID, lpData->hData);
769
770     if (lpData->hData) return bret; /* Already rendered */
771
772     if (lpData->wFlags & CF_FLAG_SYNTHESIZED)
773         bret = X11DRV_CLIPBOARD_RenderSynthesizedFormat(display, lpData);
774     else if (!X11DRV_CLIPBOARD_IsSelectionOwner())
775     {
776         if (!X11DRV_CLIPBOARD_ReadSelectionData(display, lpData))
777         {
778             ERR("Failed to cache clipboard data owned by another process. Format=%04x\n",
779                 lpData->wFormatID);
780             bret = FALSE;
781         }
782     }
783     else
784     {
785         CLIPBOARDINFO cbInfo;
786
787         if (X11DRV_CLIPBOARD_GetClipboardInfo(&cbInfo) && cbInfo.hWndOwner)
788         {
789             /* Send a WM_RENDERFORMAT message to notify the owner to render the
790              * data requested into the clipboard.
791              */
792             TRACE("Sending WM_RENDERFORMAT message to hwnd(%p)\n", cbInfo.hWndOwner);
793             SendMessageW(cbInfo.hWndOwner, WM_RENDERFORMAT, lpData->wFormatID, 0);
794
795             if (!lpData->hData) bret = FALSE;
796         }
797         else
798         {
799             ERR("hWndClipOwner is lost!\n");
800             bret = FALSE;
801         }
802     }
803
804     return bret;
805 }
806
807
808 /**************************************************************************
809  *                      CLIPBOARD_ConvertText
810  * Returns number of required/converted characters - not bytes!
811  */
812 static INT CLIPBOARD_ConvertText(WORD src_fmt, void const *src, INT src_size,
813                                  WORD dst_fmt, void *dst, INT dst_size)
814 {
815     UINT cp;
816
817     if(src_fmt == CF_UNICODETEXT)
818     {
819         switch(dst_fmt)
820         {
821         case CF_TEXT:
822             cp = CP_ACP;
823             break;
824         case CF_OEMTEXT:
825             cp = CP_OEMCP;
826             break;
827         default:
828             return 0;
829         }
830         return WideCharToMultiByte(cp, 0, src, src_size, dst, dst_size, NULL, NULL);
831     }
832
833     if(dst_fmt == CF_UNICODETEXT)
834     {
835         switch(src_fmt)
836         {
837         case CF_TEXT:
838             cp = CP_ACP;
839             break;
840         case CF_OEMTEXT:
841             cp = CP_OEMCP;
842             break;
843         default:
844             return 0;
845         }
846         return MultiByteToWideChar(cp, 0, src, src_size, dst, dst_size);
847     }
848
849     if(!dst_size) return src_size;
850
851     if(dst_size > src_size) dst_size = src_size;
852
853     if(src_fmt == CF_TEXT )
854         CharToOemBuffA(src, dst, dst_size);
855     else
856         OemToCharBuffA(src, dst, dst_size);
857
858     return dst_size;
859 }
860
861
862 /**************************************************************************
863  *                      X11DRV_CLIPBOARD_RenderSynthesizedFormat
864  */
865 static BOOL X11DRV_CLIPBOARD_RenderSynthesizedFormat(Display *display, LPWINE_CLIPDATA lpData)
866 {
867     BOOL bret = FALSE;
868
869     TRACE("\n");
870
871     if (lpData->wFlags & CF_FLAG_SYNTHESIZED)
872     {
873         UINT wFormatID = lpData->wFormatID;
874
875         if (wFormatID == CF_UNICODETEXT || wFormatID == CF_TEXT || wFormatID == CF_OEMTEXT)
876             bret = X11DRV_CLIPBOARD_RenderSynthesizedText(display, wFormatID);
877         else 
878         {
879             switch (wFormatID)
880             {
881                 case CF_DIB:
882                     bret = X11DRV_CLIPBOARD_RenderSynthesizedDIB( display );
883                     break;
884
885                 case CF_BITMAP:
886                     bret = X11DRV_CLIPBOARD_RenderSynthesizedBitmap( display );
887                     break;
888
889                 case CF_ENHMETAFILE:
890                 case CF_METAFILEPICT:
891                     FIXME("Synthesizing wFormatID(0x%08x) not implemented\n", wFormatID);
892                     break;
893
894                 default:
895                     FIXME("Called to synthesize unknown format\n");
896                     break;
897             }
898         }
899
900         lpData->wFlags &= ~CF_FLAG_SYNTHESIZED;
901     }
902
903     return bret;
904 }
905
906
907 /**************************************************************************
908  *                      X11DRV_CLIPBOARD_RenderSynthesizedText
909  *
910  * Renders synthesized text
911  */
912 static BOOL X11DRV_CLIPBOARD_RenderSynthesizedText(Display *display, UINT wFormatID)
913 {
914     LPCSTR lpstrS;
915     LPSTR  lpstrT;
916     HANDLE hData;
917     INT src_chars, dst_chars, alloc_size;
918     LPWINE_CLIPDATA lpSource = NULL;
919
920     TRACE("%04x\n", wFormatID);
921
922     if ((lpSource = X11DRV_CLIPBOARD_LookupData(wFormatID)) &&
923         lpSource->hData)
924         return TRUE;
925
926     /* Look for rendered source or non-synthesized source */
927     if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_UNICODETEXT)) &&
928         (!(lpSource->wFlags & CF_FLAG_SYNTHESIZED) || lpSource->hData))
929     {
930         TRACE("UNICODETEXT -> %04x\n", wFormatID);
931     }
932     else if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_TEXT)) &&
933         (!(lpSource->wFlags & CF_FLAG_SYNTHESIZED) || lpSource->hData))
934     {
935         TRACE("TEXT -> %04x\n", wFormatID);
936     }
937     else if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_OEMTEXT)) &&
938         (!(lpSource->wFlags & CF_FLAG_SYNTHESIZED) || lpSource->hData))
939     {
940         TRACE("OEMTEXT -> %04x\n", wFormatID);
941     }
942
943     if (!lpSource || (lpSource->wFlags & CF_FLAG_SYNTHESIZED &&
944         !lpSource->hData))
945         return FALSE;
946
947     /* Ask the clipboard owner to render the source text if necessary */
948     if (!lpSource->hData && !X11DRV_CLIPBOARD_RenderFormat(display, lpSource))
949         return FALSE;
950
951     lpstrS = GlobalLock(lpSource->hData);
952     if (!lpstrS)
953         return FALSE;
954
955     /* Text always NULL terminated */
956     if(lpSource->wFormatID == CF_UNICODETEXT)
957         src_chars = strlenW((LPCWSTR)lpstrS) + 1;
958     else
959         src_chars = strlen(lpstrS) + 1;
960
961     /* Calculate number of characters in the destination buffer */
962     dst_chars = CLIPBOARD_ConvertText(lpSource->wFormatID, lpstrS, 
963         src_chars, wFormatID, NULL, 0);
964
965     if (!dst_chars)
966         return FALSE;
967
968     TRACE("Converting from '%04x' to '%04x', %i chars\n",
969         lpSource->wFormatID, wFormatID, src_chars);
970
971     /* Convert characters to bytes */
972     if(wFormatID == CF_UNICODETEXT)
973         alloc_size = dst_chars * sizeof(WCHAR);
974     else
975         alloc_size = dst_chars;
976
977     hData = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE |
978         GMEM_DDESHARE, alloc_size);
979
980     lpstrT = GlobalLock(hData);
981
982     if (lpstrT)
983     {
984         CLIPBOARD_ConvertText(lpSource->wFormatID, lpstrS, src_chars,
985             wFormatID, lpstrT, dst_chars);
986         GlobalUnlock(hData);
987     }
988
989     GlobalUnlock(lpSource->hData);
990
991     return X11DRV_CLIPBOARD_InsertClipboardData(wFormatID, hData, 0, NULL, TRUE);
992 }
993
994
995 /**************************************************************************
996  *                      X11DRV_CLIPBOARD_RenderSynthesizedDIB
997  *
998  * Renders synthesized DIB
999  */
1000 static BOOL X11DRV_CLIPBOARD_RenderSynthesizedDIB(Display *display)
1001 {
1002     BOOL bret = FALSE;
1003     LPWINE_CLIPDATA lpSource = NULL;
1004
1005     TRACE("\n");
1006
1007     if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_DIB)) && lpSource->hData)
1008     {
1009         bret = TRUE;
1010     }
1011     /* If we have a bitmap and it's not synthesized or it has been rendered */
1012     else if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_BITMAP)) &&
1013         (!(lpSource->wFlags & CF_FLAG_SYNTHESIZED) || lpSource->hData))
1014     {
1015         /* Render source if required */
1016         if (lpSource->hData || X11DRV_CLIPBOARD_RenderFormat(display, lpSource))
1017         {
1018             HDC hdc;
1019             HGLOBAL hData;
1020
1021             hdc = GetDC(NULL);
1022             hData = X11DRV_DIB_CreateDIBFromBitmap(hdc, lpSource->hData);
1023             ReleaseDC(NULL, hdc);
1024
1025             if (hData)
1026             {
1027                 X11DRV_CLIPBOARD_InsertClipboardData(CF_DIB, hData, 0, NULL, TRUE);
1028                 bret = TRUE;
1029             }
1030         }
1031     }
1032
1033     return bret;
1034 }
1035
1036
1037 /**************************************************************************
1038  *                      X11DRV_CLIPBOARD_RenderSynthesizedBitmap
1039  *
1040  * Renders synthesized bitmap
1041  */
1042 static BOOL X11DRV_CLIPBOARD_RenderSynthesizedBitmap(Display *display)
1043 {
1044     BOOL bret = FALSE;
1045     LPWINE_CLIPDATA lpSource = NULL;
1046
1047     TRACE("\n");
1048
1049     if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_BITMAP)) && lpSource->hData)
1050     {
1051         bret = TRUE;
1052     }
1053     /* If we have a dib and it's not synthesized or it has been rendered */
1054     else if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_DIB)) &&
1055         (!(lpSource->wFlags & CF_FLAG_SYNTHESIZED) || lpSource->hData))
1056     {
1057         /* Render source if required */
1058         if (lpSource->hData || X11DRV_CLIPBOARD_RenderFormat(display, lpSource))
1059         {
1060             HDC hdc;
1061             HBITMAP hData;
1062             unsigned int offset;
1063             LPBITMAPINFOHEADER lpbmih;
1064
1065             hdc = GetDC(NULL);
1066             lpbmih = GlobalLock(lpSource->hData);
1067
1068             offset = sizeof(BITMAPINFOHEADER)
1069                   + ((lpbmih->biBitCount <= 8) ? (sizeof(RGBQUAD) *
1070                     (1 << lpbmih->biBitCount)) : 0);
1071
1072             hData = CreateDIBitmap(hdc, lpbmih, CBM_INIT, (LPBYTE)lpbmih +
1073                 offset, (LPBITMAPINFO) lpbmih, DIB_RGB_COLORS);
1074
1075             GlobalUnlock(lpSource->hData);
1076             ReleaseDC(NULL, hdc);
1077
1078             if (hData)
1079             {
1080                 X11DRV_CLIPBOARD_InsertClipboardData(CF_BITMAP, hData, 0, NULL, TRUE);
1081                 bret = TRUE;
1082             }
1083         }
1084     }
1085
1086     return bret;
1087 }
1088
1089
1090 /**************************************************************************
1091  *              X11DRV_CLIPBOARD_ImportXAString
1092  *
1093  *  Import XA_STRING, converting the string to CF_TEXT.
1094  */
1095 static HANDLE X11DRV_CLIPBOARD_ImportXAString(Display *display, Window w, Atom prop)
1096 {
1097     LPBYTE lpdata;
1098     unsigned long cbytes;
1099     LPSTR lpstr;
1100     unsigned long i, inlcount = 0;
1101     HANDLE hText = 0;
1102
1103     if (!X11DRV_CLIPBOARD_ReadProperty(display, w, prop, &lpdata, &cbytes))
1104         return 0;
1105
1106     for (i = 0; i <= cbytes; i++)
1107     {
1108         if (lpdata[i] == '\n')
1109             inlcount++;
1110     }
1111
1112     if ((hText = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, cbytes + inlcount + 1)))
1113     {
1114         lpstr = GlobalLock(hText);
1115
1116         for (i = 0, inlcount = 0; i <= cbytes; i++)
1117         {
1118             if (lpdata[i] == '\n')
1119                 lpstr[inlcount++] = '\r';
1120
1121             lpstr[inlcount++] = lpdata[i];
1122         }
1123
1124         GlobalUnlock(hText);
1125     }
1126
1127     /* Free the retrieved property data */
1128     HeapFree(GetProcessHeap(), 0, lpdata);
1129
1130     return hText;
1131 }
1132
1133
1134 /**************************************************************************
1135  *              X11DRV_CLIPBOARD_ImportUTF8
1136  *
1137  *  Import XA_STRING, converting the string to CF_UNICODE.
1138  */
1139 static HANDLE X11DRV_CLIPBOARD_ImportUTF8(Display *display, Window w, Atom prop)
1140 {
1141     LPBYTE lpdata;
1142     unsigned long cbytes;
1143     LPSTR lpstr;
1144     unsigned long i, inlcount = 0;
1145     HANDLE hUnicodeText = 0;
1146
1147     if (!X11DRV_CLIPBOARD_ReadProperty(display, w, prop, &lpdata, &cbytes))
1148         return 0;
1149
1150     for (i = 0; i <= cbytes; i++)
1151     {
1152         if (lpdata[i] == '\n')
1153             inlcount++;
1154     }
1155
1156     if ((lpstr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbytes + inlcount + 1)))
1157     {
1158         UINT count;
1159
1160         for (i = 0, inlcount = 0; i <= cbytes; i++)
1161         {
1162             if (lpdata[i] == '\n')
1163                 lpstr[inlcount++] = '\r';
1164
1165             lpstr[inlcount++] = lpdata[i];
1166         }
1167
1168         count = MultiByteToWideChar(CP_UTF8, 0, lpstr, -1, NULL, 0);
1169         hUnicodeText = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, count * sizeof(WCHAR));
1170
1171         if (hUnicodeText)
1172         {
1173             WCHAR *textW = GlobalLock(hUnicodeText);
1174             MultiByteToWideChar(CP_UTF8, 0, lpstr, -1, textW, count);
1175             GlobalUnlock(hUnicodeText);
1176         }
1177
1178         HeapFree(GetProcessHeap(), 0, lpstr);
1179     }
1180
1181     /* Free the retrieved property data */
1182     HeapFree(GetProcessHeap(), 0, lpdata);
1183
1184     return hUnicodeText;
1185 }
1186
1187
1188 /**************************************************************************
1189  *              X11DRV_CLIPBOARD_ImportCompoundText
1190  *
1191  *  Import COMPOUND_TEXT to CF_UNICODE
1192  */
1193 static HANDLE X11DRV_CLIPBOARD_ImportCompoundText(Display *display, Window w, Atom prop)
1194 {
1195     int i, j, ret;
1196     char** srcstr;
1197     int count, lcount;
1198     int srclen, destlen;
1199     HANDLE hUnicodeText;
1200     XTextProperty txtprop;
1201
1202     if (!X11DRV_CLIPBOARD_ReadProperty(display, w, prop, &txtprop.value, &txtprop.nitems))
1203     {
1204         return 0;
1205     }
1206
1207     txtprop.encoding = x11drv_atom(COMPOUND_TEXT);
1208     txtprop.format = 8;
1209     wine_tsx11_lock();
1210     ret = XmbTextPropertyToTextList(display, &txtprop, &srcstr, &count);
1211     wine_tsx11_unlock();
1212     HeapFree(GetProcessHeap(), 0, txtprop.value);
1213     if (ret != Success || !count) return 0;
1214
1215     TRACE("Importing %d line(s)\n", count);
1216
1217     /* Compute number of lines */
1218     srclen = strlen(srcstr[0]);
1219     for (i = 0, lcount = 0; i <= srclen; i++)
1220     {
1221         if (srcstr[0][i] == '\n')
1222             lcount++;
1223     }
1224
1225     destlen = MultiByteToWideChar(CP_UNIXCP, 0, srcstr[0], -1, NULL, 0);
1226
1227     TRACE("lcount = %d, destlen=%d, srcstr %s\n", lcount, destlen, srcstr[0]);
1228
1229     if ((hUnicodeText = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, (destlen + lcount + 1) * sizeof(WCHAR))))
1230     {
1231         WCHAR *deststr = GlobalLock(hUnicodeText);
1232         MultiByteToWideChar(CP_UNIXCP, 0, srcstr[0], -1, deststr, destlen);
1233
1234         if (lcount)
1235         {
1236             for (i = destlen - 1, j = destlen + lcount - 1; i >= 0; i--, j--)
1237             {
1238                 deststr[j] = deststr[i];
1239
1240                 if (deststr[i] == '\n')
1241                     deststr[--j] = '\r';
1242             }
1243         }
1244
1245         GlobalUnlock(hUnicodeText);
1246     }
1247
1248     wine_tsx11_lock();
1249     XFreeStringList(srcstr);
1250     wine_tsx11_unlock();
1251
1252     return hUnicodeText;
1253 }
1254
1255
1256 /**************************************************************************
1257  *              X11DRV_CLIPBOARD_ImportXAPIXMAP
1258  *
1259  *  Import XA_PIXMAP, converting the image to CF_DIB.
1260  */
1261 static HANDLE X11DRV_CLIPBOARD_ImportXAPIXMAP(Display *display, Window w, Atom prop)
1262 {
1263     HWND hwnd;
1264     HDC hdc;
1265     LPBYTE lpdata;
1266     unsigned long cbytes;
1267     Pixmap *pPixmap;
1268     HANDLE hClipData = 0;
1269
1270     if (X11DRV_CLIPBOARD_ReadProperty(display, w, prop, &lpdata, &cbytes))
1271     {
1272         pPixmap = (Pixmap *) lpdata;
1273
1274         hwnd = GetOpenClipboardWindow();
1275         hdc = GetDC(hwnd);
1276
1277         hClipData = X11DRV_DIB_CreateDIBFromPixmap(*pPixmap, hdc);
1278         ReleaseDC(hwnd, hdc);
1279
1280         /* Free the retrieved property data */
1281         HeapFree(GetProcessHeap(), 0, lpdata);
1282     }
1283
1284     return hClipData;
1285 }
1286
1287
1288 /**************************************************************************
1289  *              X11DRV_CLIPBOARD_ImportImageBmp
1290  *
1291  *  Import image/bmp, converting the image to CF_DIB.
1292  */
1293 static HANDLE X11DRV_CLIPBOARD_ImportImageBmp(Display *display, Window w, Atom prop)
1294 {
1295     LPBYTE lpdata;
1296     unsigned long cbytes;
1297     HANDLE hClipData = 0;
1298
1299     if (X11DRV_CLIPBOARD_ReadProperty(display, w, prop, &lpdata, &cbytes))
1300     {
1301         BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)lpdata;
1302
1303         if (cbytes >= sizeof(BITMAPFILEHEADER)+sizeof(BITMAPCOREHEADER) &&
1304             bfh->bfType == 0x4d42 /* "BM" */)
1305         {
1306             BITMAPINFO *bmi = (BITMAPINFO*)(bfh+1);
1307             HBITMAP hbmp;
1308             HDC hdc;
1309
1310             hdc = GetDC(0);
1311             hbmp = CreateDIBitmap(
1312                 hdc,
1313                 &(bmi->bmiHeader),
1314                 CBM_INIT,
1315                 lpdata+bfh->bfOffBits,
1316                 bmi,
1317                 DIB_RGB_COLORS
1318                 );
1319
1320             hClipData = X11DRV_DIB_CreateDIBFromBitmap(hdc, hbmp);
1321
1322             DeleteObject(hbmp);
1323             ReleaseDC(0, hdc);
1324         }
1325
1326         /* Free the retrieved property data */
1327         HeapFree(GetProcessHeap(), 0, lpdata);
1328     }
1329
1330     return hClipData;
1331 }
1332
1333
1334 /**************************************************************************
1335  *              X11DRV_CLIPBOARD_ImportMetaFilePict
1336  *
1337  *  Import MetaFilePict.
1338  */
1339 static HANDLE X11DRV_CLIPBOARD_ImportMetaFilePict(Display *display, Window w, Atom prop)
1340 {
1341     LPBYTE lpdata;
1342     unsigned long cbytes;
1343     HANDLE hClipData = 0;
1344
1345     if (X11DRV_CLIPBOARD_ReadProperty(display, w, prop, &lpdata, &cbytes))
1346     {
1347         if (cbytes)
1348             hClipData = X11DRV_CLIPBOARD_SerializeMetafile(CF_METAFILEPICT, lpdata, (LPDWORD)&cbytes, FALSE);
1349
1350         /* Free the retrieved property data */
1351         HeapFree(GetProcessHeap(), 0, lpdata);
1352     }
1353
1354     return hClipData;
1355 }
1356
1357
1358 /**************************************************************************
1359  *              X11DRV_ImportEnhMetaFile
1360  *
1361  *  Import EnhMetaFile.
1362  */
1363 static HANDLE X11DRV_CLIPBOARD_ImportEnhMetaFile(Display *display, Window w, Atom prop)
1364 {
1365     LPBYTE lpdata;
1366     unsigned long cbytes;
1367     HANDLE hClipData = 0;
1368
1369     if (X11DRV_CLIPBOARD_ReadProperty(display, w, prop, &lpdata, &cbytes))
1370     {
1371         if (cbytes)
1372             hClipData = X11DRV_CLIPBOARD_SerializeMetafile(CF_ENHMETAFILE, lpdata, (LPDWORD)&cbytes, FALSE);
1373
1374         /* Free the retrieved property data */
1375         HeapFree(GetProcessHeap(), 0, lpdata);
1376     }
1377
1378     return hClipData;
1379 }
1380
1381
1382 /**************************************************************************
1383  *              X11DRV_ImportClipbordaData
1384  *
1385  *  Generic import clipboard data routine.
1386  */
1387 static HANDLE X11DRV_CLIPBOARD_ImportClipboardData(Display *display, Window w, Atom prop)
1388 {
1389     LPVOID lpClipData;
1390     LPBYTE lpdata;
1391     unsigned long cbytes;
1392     HANDLE hClipData = 0;
1393
1394     if (X11DRV_CLIPBOARD_ReadProperty(display, w, prop, &lpdata, &cbytes))
1395     {
1396         if (cbytes)
1397         {
1398             /* Turn on the DDESHARE flag to enable shared 32 bit memory */
1399             hClipData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, cbytes);
1400             if (hClipData == 0)
1401                 return NULL;
1402
1403             if ((lpClipData = GlobalLock(hClipData)))
1404             {
1405                 memcpy(lpClipData, lpdata, cbytes);
1406                 GlobalUnlock(hClipData);
1407             }
1408             else
1409             {
1410                 GlobalFree(hClipData);
1411                 hClipData = 0;
1412             }
1413         }
1414
1415         /* Free the retrieved property data */
1416         HeapFree(GetProcessHeap(), 0, lpdata);
1417     }
1418
1419     return hClipData;
1420 }
1421
1422
1423 /**************************************************************************
1424                 X11DRV_CLIPBOARD_ExportClipboardData
1425  *
1426  *  Generic export clipboard data routine.
1427  */
1428 static HANDLE X11DRV_CLIPBOARD_ExportClipboardData(Display *display, Window requestor, Atom aTarget,
1429                                             Atom rprop, LPWINE_CLIPDATA lpData, LPDWORD lpBytes)
1430 {
1431     LPVOID lpClipData;
1432     UINT datasize = 0;
1433     HANDLE hClipData = 0;
1434
1435     *lpBytes = 0; /* Assume failure */
1436
1437     if (!X11DRV_CLIPBOARD_RenderFormat(display, lpData))
1438         ERR("Failed to export %04x format\n", lpData->wFormatID);
1439     else
1440     {
1441         datasize = GlobalSize(lpData->hData);
1442
1443         hClipData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, datasize);
1444         if (hClipData == 0) return NULL;
1445
1446         if ((lpClipData = GlobalLock(hClipData)))
1447         {
1448             LPVOID lpdata = GlobalLock(lpData->hData);
1449
1450             memcpy(lpClipData, lpdata, datasize);
1451             *lpBytes = datasize;
1452
1453             GlobalUnlock(lpData->hData);
1454             GlobalUnlock(hClipData);
1455         } else {
1456             GlobalFree(hClipData);
1457             hClipData = 0;
1458         }
1459     }
1460
1461     return hClipData;
1462 }
1463
1464
1465 /**************************************************************************
1466  *              X11DRV_CLIPBOARD_ExportXAString
1467  *
1468  *  Export CF_TEXT converting the string to XA_STRING.
1469  *  Helper function for X11DRV_CLIPBOARD_ExportString.
1470  */
1471 static HANDLE X11DRV_CLIPBOARD_ExportXAString(LPWINE_CLIPDATA lpData, LPDWORD lpBytes)
1472 {
1473     UINT i, j;
1474     UINT size;
1475     LPSTR text, lpstr = NULL;
1476
1477     *lpBytes = 0; /* Assume return has zero bytes */
1478
1479     text = GlobalLock(lpData->hData);
1480     size = strlen(text);
1481
1482     /* remove carriage returns */
1483     lpstr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size + 1);
1484     if (lpstr == NULL)
1485         goto done;
1486
1487     for (i = 0,j = 0; i < size && text[i]; i++)
1488     {
1489         if (text[i] == '\r' && (text[i+1] == '\n' || text[i+1] == '\0'))
1490             continue;
1491         lpstr[j++] = text[i];
1492     }
1493
1494     lpstr[j]='\0';
1495     *lpBytes = j; /* Number of bytes in string */
1496
1497 done:
1498     HeapFree(GetProcessHeap(), 0, text);
1499     GlobalUnlock(lpData->hData);
1500
1501     return lpstr;
1502 }
1503
1504
1505 /**************************************************************************
1506  *              X11DRV_CLIPBOARD_ExportUTF8String
1507  *
1508  *  Export CF_UNICODE converting the string to UTF8.
1509  *  Helper function for X11DRV_CLIPBOARD_ExportString.
1510  */
1511 static HANDLE X11DRV_CLIPBOARD_ExportUTF8String(LPWINE_CLIPDATA lpData, LPDWORD lpBytes)
1512 {
1513     UINT i, j;
1514     UINT size;
1515     LPWSTR uni_text;
1516     LPSTR text, lpstr = NULL;
1517
1518     *lpBytes = 0; /* Assume return has zero bytes */
1519
1520     uni_text = GlobalLock(lpData->hData);
1521
1522     size = WideCharToMultiByte(CP_UTF8, 0, uni_text, -1, NULL, 0, NULL, NULL);
1523
1524     text = HeapAlloc(GetProcessHeap(), 0, size);
1525     if (!text)
1526         goto done;
1527     WideCharToMultiByte(CP_UTF8, 0, uni_text, -1, text, size, NULL, NULL);
1528
1529     /* remove carriage returns */
1530     lpstr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size--);
1531     if (lpstr == NULL)
1532         goto done;
1533
1534     for (i = 0,j = 0; i < size && text[i]; i++)
1535     {
1536         if (text[i] == '\r' && (text[i+1] == '\n' || text[i+1] == '\0'))
1537             continue;
1538         lpstr[j++] = text[i];
1539     }
1540     lpstr[j]='\0';
1541
1542     *lpBytes = j; /* Number of bytes in string */
1543
1544 done:
1545     HeapFree(GetProcessHeap(), 0, text);
1546     GlobalUnlock(lpData->hData);
1547
1548     return lpstr;
1549 }
1550
1551
1552
1553 /**************************************************************************
1554  *              X11DRV_CLIPBOARD_ExportCompoundText
1555  *
1556  *  Export CF_UNICODE to COMPOUND_TEXT
1557  *  Helper function for X11DRV_CLIPBOARD_ExportString.
1558  */
1559 static HANDLE X11DRV_CLIPBOARD_ExportCompoundText(Display *display, Window requestor, Atom aTarget, Atom rprop,
1560     LPWINE_CLIPDATA lpData, LPDWORD lpBytes)
1561 {
1562     char* lpstr = 0;
1563     XTextProperty prop;
1564     XICCEncodingStyle style;
1565     UINT i, j;
1566     UINT size;
1567     LPWSTR uni_text;
1568
1569     uni_text = GlobalLock(lpData->hData);
1570
1571     size = WideCharToMultiByte(CP_UNIXCP, 0, uni_text, -1, NULL, 0, NULL, NULL);
1572     lpstr = HeapAlloc(GetProcessHeap(), 0, size);
1573     if (!lpstr)
1574         return 0;
1575
1576     WideCharToMultiByte(CP_UNIXCP, 0, uni_text, -1, lpstr, size, NULL, NULL);
1577
1578     /* remove carriage returns */
1579     for (i = 0, j = 0; i < size && lpstr[i]; i++)
1580     {
1581         if (lpstr[i] == '\r' && (lpstr[i+1] == '\n' || lpstr[i+1] == '\0'))
1582             continue;
1583         lpstr[j++] = lpstr[i];
1584     }
1585     lpstr[j]='\0';
1586
1587     GlobalUnlock(lpData->hData);
1588
1589     if (aTarget == x11drv_atom(COMPOUND_TEXT))
1590         style = XCompoundTextStyle;
1591     else
1592         style = XStdICCTextStyle;
1593
1594     /* Update the X property */
1595     wine_tsx11_lock();
1596     if (XmbTextListToTextProperty(display, &lpstr, 1, style, &prop) == Success)
1597     {
1598         XSetTextProperty(display, requestor, &prop, rprop);
1599         XFree(prop.value);
1600     }
1601     wine_tsx11_unlock();
1602
1603     HeapFree(GetProcessHeap(), 0, lpstr);
1604
1605     return 0;
1606 }
1607
1608 /**************************************************************************
1609  *              X11DRV_CLIPBOARD_ExportString
1610  *
1611  *  Export string
1612  */
1613 static HANDLE X11DRV_CLIPBOARD_ExportString(Display *display, Window requestor, Atom aTarget, Atom rprop,
1614                                      LPWINE_CLIPDATA lpData, LPDWORD lpBytes)
1615 {
1616     if (X11DRV_CLIPBOARD_RenderFormat(display, lpData))
1617     {
1618         if (aTarget == XA_STRING)
1619             return X11DRV_CLIPBOARD_ExportXAString(lpData, lpBytes);
1620         else if (aTarget == x11drv_atom(COMPOUND_TEXT) || aTarget == x11drv_atom(TEXT))
1621             return X11DRV_CLIPBOARD_ExportCompoundText(display, requestor, aTarget,
1622                 rprop, lpData, lpBytes);
1623         else
1624         {
1625             TRACE("Exporting target %ld to default UTF8_STRING\n", aTarget);
1626             return X11DRV_CLIPBOARD_ExportUTF8String(lpData, lpBytes);
1627         }
1628     }
1629     else
1630         ERR("Failed to render %04x format\n", lpData->wFormatID);
1631
1632     return 0;
1633 }
1634
1635
1636 /**************************************************************************
1637  *              X11DRV_CLIPBOARD_ExportXAPIXMAP
1638  *
1639  *  Export CF_DIB to XA_PIXMAP.
1640  */
1641 static HANDLE X11DRV_CLIPBOARD_ExportXAPIXMAP(Display *display, Window requestor, Atom aTarget, Atom rprop,
1642     LPWINE_CLIPDATA lpdata, LPDWORD lpBytes)
1643 {
1644     HDC hdc;
1645     HANDLE hData;
1646     unsigned char* lpData;
1647
1648     if (!X11DRV_CLIPBOARD_RenderFormat(display, lpdata))
1649     {
1650         ERR("Failed to export %04x format\n", lpdata->wFormatID);
1651         return 0;
1652     }
1653
1654     if (!lpdata->drvData) /* If not already rendered */
1655     {
1656         /* For convert from packed DIB to Pixmap */
1657         hdc = GetDC(0);
1658         lpdata->drvData = (UINT) X11DRV_DIB_CreatePixmapFromDIB(lpdata->hData, hdc);
1659         ReleaseDC(0, hdc);
1660     }
1661
1662     *lpBytes = sizeof(Pixmap); /* pixmap is a 32bit value */
1663
1664     /* Wrap pixmap so we can return a handle */
1665     hData = GlobalAlloc(0, *lpBytes);
1666     lpData = GlobalLock(hData);
1667     memcpy(lpData, &lpdata->drvData, *lpBytes);
1668     GlobalUnlock(hData);
1669
1670     return hData;
1671 }
1672
1673
1674 /**************************************************************************
1675  *              X11DRV_CLIPBOARD_ExportImageBmp
1676  *
1677  *  Export CF_DIB to image/bmp.
1678  */
1679 static HANDLE X11DRV_CLIPBOARD_ExportImageBmp(Display *display, Window requestor, Atom aTarget, Atom rprop,
1680     LPWINE_CLIPDATA lpdata, LPDWORD lpBytes)
1681 {
1682     HANDLE hpackeddib;
1683     LPBYTE dibdata;
1684     UINT bmpsize;
1685     HANDLE hbmpdata;
1686     LPBYTE bmpdata;
1687     BITMAPFILEHEADER *bfh;
1688
1689     *lpBytes = 0;
1690
1691     if (!X11DRV_CLIPBOARD_RenderFormat(display, lpdata))
1692     {
1693         ERR("Failed to export %04x format\n", lpdata->wFormatID);
1694         return 0;
1695     }
1696
1697     hpackeddib = lpdata->hData;
1698
1699     dibdata = GlobalLock(hpackeddib);
1700     if (!dibdata)
1701     {
1702         ERR("Failed to lock packed DIB\n");
1703         return 0;
1704     }
1705
1706     bmpsize = sizeof(BITMAPFILEHEADER) + GlobalSize(hpackeddib);
1707
1708     hbmpdata = GlobalAlloc(0, bmpsize);
1709
1710     if (hbmpdata)
1711     {
1712         bmpdata = GlobalLock(hbmpdata);
1713
1714         if (!bmpdata)
1715         {
1716             GlobalFree(hbmpdata);
1717             GlobalUnlock(hpackeddib);
1718             return 0;
1719         }
1720
1721         /* bitmap file header */
1722         bfh = (BITMAPFILEHEADER*)bmpdata;
1723         bfh->bfType = 0x4d42; /* "BM" */
1724         bfh->bfSize = bmpsize;
1725         bfh->bfReserved1 = 0;
1726         bfh->bfReserved2 = 0;
1727         bfh->bfOffBits = sizeof(BITMAPFILEHEADER) + bitmap_info_size((BITMAPINFO*)dibdata, DIB_RGB_COLORS);
1728
1729         /* rest of bitmap is the same as the packed dib */
1730         memcpy(bfh+1, dibdata, bmpsize-sizeof(BITMAPFILEHEADER));
1731
1732         *lpBytes = bmpsize;
1733
1734         GlobalUnlock(hbmpdata);
1735     }
1736
1737     GlobalUnlock(hpackeddib);
1738
1739     return hbmpdata;
1740 }
1741
1742
1743 /**************************************************************************
1744  *              X11DRV_CLIPBOARD_ExportMetaFilePict
1745  *
1746  *  Export MetaFilePict.
1747  */
1748 static HANDLE X11DRV_CLIPBOARD_ExportMetaFilePict(Display *display, Window requestor, Atom aTarget, Atom rprop,
1749                                            LPWINE_CLIPDATA lpdata, LPDWORD lpBytes)
1750 {
1751     if (!X11DRV_CLIPBOARD_RenderFormat(display, lpdata))
1752     {
1753         ERR("Failed to export %04x format\n", lpdata->wFormatID);
1754         return 0;
1755     }
1756
1757     return X11DRV_CLIPBOARD_SerializeMetafile(CF_METAFILEPICT, lpdata->hData, lpBytes, TRUE);
1758 }
1759
1760
1761 /**************************************************************************
1762  *              X11DRV_CLIPBOARD_ExportEnhMetaFile
1763  *
1764  *  Export EnhMetaFile.
1765  */
1766 static HANDLE X11DRV_CLIPBOARD_ExportEnhMetaFile(Display *display, Window requestor, Atom aTarget, Atom rprop,
1767                                           LPWINE_CLIPDATA lpdata, LPDWORD lpBytes)
1768 {
1769     if (!X11DRV_CLIPBOARD_RenderFormat(display, lpdata))
1770     {
1771         ERR("Failed to export %04x format\n", lpdata->wFormatID);
1772         return 0;
1773     }
1774
1775     return X11DRV_CLIPBOARD_SerializeMetafile(CF_ENHMETAFILE, lpdata->hData, lpBytes, TRUE);
1776 }
1777
1778
1779 /**************************************************************************
1780  *              get_html_description_field
1781  *
1782  *  Find the value of a field in an HTML Format description.
1783  */
1784 static LPCSTR get_html_description_field(LPCSTR data, LPCSTR keyword)
1785 {
1786     LPCSTR pos=data;
1787
1788     while (pos && *pos && *pos != '<')
1789     {
1790         if (memcmp(pos, keyword, strlen(keyword)) == 0)
1791             return pos+strlen(keyword);
1792
1793         pos = strchr(pos, '\n');
1794         if (pos) pos++;
1795     }
1796
1797     return NULL;
1798 }
1799
1800
1801 /**************************************************************************
1802  *              X11DRV_CLIPBOARD_ExportTextHtml
1803  *
1804  *  Export HTML Format to text/html.
1805  *
1806  * FIXME: We should attempt to add an <a base> tag and convert windows paths.
1807  */
1808 static HANDLE X11DRV_CLIPBOARD_ExportTextHtml(Display *display, Window requestor, Atom aTarget,
1809     Atom rprop, LPWINE_CLIPDATA lpdata, LPDWORD lpBytes)
1810 {
1811     HANDLE hdata;
1812     UINT datasize;
1813     LPCSTR data, field_value;
1814     UINT fragmentstart, fragmentend, htmlsize;
1815     HANDLE hhtmldata=NULL;
1816     LPSTR htmldata;
1817
1818     *lpBytes = 0;
1819
1820     if (!X11DRV_CLIPBOARD_RenderFormat(display, lpdata))
1821     {
1822         ERR("Failed to export %04x format\n", lpdata->wFormatID);
1823         return 0;
1824     }
1825
1826     hdata = lpdata->hData;
1827
1828     datasize = GlobalSize(hdata);
1829
1830     data = GlobalLock(hdata);
1831     if (!data)
1832     {
1833         ERR("Failed to lock HTML Format data\n");
1834         return 0;
1835     }
1836
1837     /* read the important fields */
1838     field_value = get_html_description_field(data, "StartFragment:");
1839     if (!field_value)
1840     {
1841         ERR("Couldn't find StartFragment value\n");
1842         goto end;
1843     }
1844     fragmentstart = atoi(field_value);
1845
1846     field_value = get_html_description_field(data, "EndFragment:");
1847     if (!field_value)
1848     {
1849         ERR("Couldn't find EndFragment value\n");
1850         goto end;
1851     }
1852     fragmentend = atoi(field_value);
1853
1854     /* export only the fragment */
1855     htmlsize = fragmentend - fragmentstart + 1;
1856
1857     hhtmldata = GlobalAlloc(0, htmlsize);
1858
1859     if (hhtmldata)
1860     {
1861         htmldata = GlobalLock(hhtmldata);
1862
1863         if (!htmldata)
1864         {
1865             GlobalFree(hhtmldata);
1866             htmldata = NULL;
1867             goto end;
1868         }
1869
1870         memcpy(htmldata, &data[fragmentstart], fragmentend-fragmentstart);
1871         htmldata[htmlsize-1] = '\0';
1872
1873         *lpBytes = htmlsize;
1874
1875         GlobalUnlock(htmldata);
1876     }
1877
1878 end:
1879
1880     GlobalUnlock(hdata);
1881
1882     return hhtmldata;
1883 }
1884
1885
1886 /**************************************************************************
1887  *              X11DRV_CLIPBOARD_QueryTargets
1888  */
1889 static BOOL X11DRV_CLIPBOARD_QueryTargets(Display *display, Window w, Atom selection,
1890     Atom target, XEvent *xe)
1891 {
1892     INT i;
1893     Bool res;
1894
1895     wine_tsx11_lock();
1896     XConvertSelection(display, selection, target,
1897         x11drv_atom(SELECTION_DATA), w, CurrentTime);
1898     wine_tsx11_unlock();
1899
1900     /*
1901      * Wait until SelectionNotify is received
1902      */
1903     for (i = 0; i < SELECTION_RETRIES; i++)
1904     {
1905         wine_tsx11_lock();
1906         res = XCheckTypedWindowEvent(display, w, SelectionNotify, xe);
1907         wine_tsx11_unlock();
1908         if (res && xe->xselection.selection == selection) break;
1909
1910         usleep(SELECTION_WAIT);
1911     }
1912
1913     if (i == SELECTION_RETRIES)
1914     {
1915         ERR("Timed out waiting for SelectionNotify event\n");
1916         return FALSE;
1917     }
1918     /* Verify that the selection returned a valid TARGETS property */
1919     if ((xe->xselection.target != target) || (xe->xselection.property == None))
1920     {
1921         /* Selection owner failed to respond or we missed the SelectionNotify */
1922         WARN("Failed to retrieve TARGETS for selection %ld.\n", selection);
1923         return FALSE;
1924     }
1925
1926     return TRUE;
1927 }
1928
1929
1930 static int is_atom_error( Display *display, XErrorEvent *event, void *arg )
1931 {
1932     return (event->error_code == BadAtom);
1933 }
1934
1935 /**************************************************************************
1936  *              X11DRV_CLIPBOARD_InsertSelectionProperties
1937  *
1938  * Mark properties available for future retrieval.
1939  */
1940 static VOID X11DRV_CLIPBOARD_InsertSelectionProperties(Display *display, Atom* properties, UINT count)
1941 {
1942      UINT i, nb_atoms = 0;
1943      Atom *atoms = NULL;
1944
1945      /* Cache these formats in the clipboard cache */
1946      for (i = 0; i < count; i++)
1947      {
1948          LPWINE_CLIPFORMAT lpFormat = X11DRV_CLIPBOARD_LookupProperty(NULL, properties[i]);
1949
1950          if (lpFormat)
1951          {
1952              /* We found at least one Window's format that mapps to the property.
1953               * Continue looking for more.
1954               *
1955               * If more than one property map to a Window's format then we use the first 
1956               * one and ignore the rest.
1957               */
1958              while (lpFormat)
1959              {
1960                  TRACE("Atom#%d Property(%d): --> FormatID(%04x) %s\n",
1961                        i, lpFormat->drvData, lpFormat->wFormatID, debugstr_w(lpFormat->Name));
1962                  X11DRV_CLIPBOARD_InsertClipboardData(lpFormat->wFormatID, 0, 0, lpFormat, FALSE);
1963                  lpFormat = X11DRV_CLIPBOARD_LookupProperty(lpFormat, properties[i]);
1964              }
1965          }
1966          else if (properties[i])
1967          {
1968              /* add it to the list of atoms that we don't know about yet */
1969              if (!atoms) atoms = HeapAlloc( GetProcessHeap(), 0,
1970                                             (count - i) * sizeof(*atoms) );
1971              if (atoms) atoms[nb_atoms++] = properties[i];
1972          }
1973      }
1974
1975      /* query all unknown atoms in one go */
1976      if (atoms)
1977      {
1978          char **names = HeapAlloc( GetProcessHeap(), 0, nb_atoms * sizeof(*names) );
1979          if (names)
1980          {
1981              X11DRV_expect_error( display, is_atom_error, NULL );
1982              if (!XGetAtomNames( display, atoms, nb_atoms, names )) nb_atoms = 0;
1983              if (X11DRV_check_error())
1984              {
1985                  WARN( "got some bad atoms, ignoring\n" );
1986                  nb_atoms = 0;
1987              }
1988              for (i = 0; i < nb_atoms; i++)
1989              {
1990                  WINE_CLIPFORMAT *lpFormat;
1991                  LPWSTR wname;
1992                  int len = MultiByteToWideChar(CP_UNIXCP, 0, names[i], -1, NULL, 0);
1993                  wname = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
1994                  MultiByteToWideChar(CP_UNIXCP, 0, names[i], -1, wname, len);
1995
1996                  lpFormat = register_format( wname, atoms[i] );
1997                  HeapFree(GetProcessHeap(), 0, wname);
1998                  if (!lpFormat)
1999                  {
2000                      ERR("Failed to register %s property. Type will not be cached.\n", names[i]);
2001                      continue;
2002                  }
2003                  TRACE("Atom#%d Property(%d): --> FormatID(%04x) %s\n",
2004                        i, lpFormat->drvData, lpFormat->wFormatID, debugstr_w(lpFormat->Name));
2005                  X11DRV_CLIPBOARD_InsertClipboardData(lpFormat->wFormatID, 0, 0, lpFormat, FALSE);
2006              }
2007              wine_tsx11_lock();
2008              for (i = 0; i < nb_atoms; i++) XFree( names[i] );
2009              wine_tsx11_unlock();
2010              HeapFree( GetProcessHeap(), 0, names );
2011          }
2012          HeapFree( GetProcessHeap(), 0, atoms );
2013      }
2014 }
2015
2016
2017 /**************************************************************************
2018  *              X11DRV_CLIPBOARD_QueryAvailableData
2019  *
2020  * Caches the list of data formats available from the current selection.
2021  * This queries the selection owner for the TARGETS property and saves all
2022  * reported property types.
2023  */
2024 static int X11DRV_CLIPBOARD_QueryAvailableData(Display *display, LPCLIPBOARDINFO lpcbinfo)
2025 {
2026     XEvent         xe;
2027     Atom           atype=AnyPropertyType;
2028     int            aformat;
2029     unsigned long  remain;
2030     Atom*          targetList=NULL;
2031     Window         w;
2032     unsigned long  cSelectionTargets = 0;
2033
2034     if (selectionAcquired & (S_PRIMARY | S_CLIPBOARD))
2035     {
2036         ERR("Received request to cache selection but process is owner=(%08x)\n", 
2037             (unsigned) selectionWindow);
2038         return -1; /* Prevent self request */
2039     }
2040
2041     w = thread_selection_wnd();
2042     if (!w)
2043     {
2044         ERR("No window available to retrieve selection!\n");
2045         return -1;
2046     }
2047
2048     /*
2049      * Query the selection owner for the TARGETS property
2050      */
2051     wine_tsx11_lock();
2052     if ((use_primary_selection && XGetSelectionOwner(display,XA_PRIMARY)) ||
2053         XGetSelectionOwner(display,x11drv_atom(CLIPBOARD)))
2054     {
2055         wine_tsx11_unlock();
2056         if (use_primary_selection && (X11DRV_CLIPBOARD_QueryTargets(display, w, XA_PRIMARY, x11drv_atom(TARGETS), &xe)))
2057             selectionCacheSrc = XA_PRIMARY;
2058         else if (X11DRV_CLIPBOARD_QueryTargets(display, w, x11drv_atom(CLIPBOARD), x11drv_atom(TARGETS), &xe))
2059             selectionCacheSrc = x11drv_atom(CLIPBOARD);
2060         else
2061         {
2062             Atom xstr = XA_STRING;
2063
2064             /* Selection Owner doesn't understand TARGETS, try retrieving XA_STRING */
2065             if (X11DRV_CLIPBOARD_QueryTargets(display, w, XA_PRIMARY, XA_STRING, &xe))
2066             {
2067                 X11DRV_CLIPBOARD_InsertSelectionProperties(display, &xstr, 1);
2068                 selectionCacheSrc = XA_PRIMARY;
2069                 return 1;
2070             }
2071             else if (X11DRV_CLIPBOARD_QueryTargets(display, w, x11drv_atom(CLIPBOARD), XA_STRING, &xe))
2072             {
2073                 X11DRV_CLIPBOARD_InsertSelectionProperties(display, &xstr, 1);
2074                 selectionCacheSrc = x11drv_atom(CLIPBOARD);
2075                 return 1;
2076             }
2077             else
2078             {
2079                 WARN("Failed to query selection owner for available data.\n");
2080                 return -1;
2081             }
2082         }
2083     }
2084     else /* No selection owner so report 0 targets available */
2085     {
2086         wine_tsx11_unlock();
2087         return 0;
2088     }
2089
2090     /* Read the TARGETS property contents */
2091     wine_tsx11_lock();
2092     if(XGetWindowProperty(display, xe.xselection.requestor, xe.xselection.property,
2093         0, 0x3FFF, True, AnyPropertyType/*XA_ATOM*/, &atype, &aformat, &cSelectionTargets, 
2094         &remain, (unsigned char**)&targetList) != Success)
2095     {
2096         wine_tsx11_unlock();
2097         WARN("Failed to read TARGETS property\n");
2098     }
2099     else
2100     {
2101         wine_tsx11_unlock();
2102        TRACE("Type %lx,Format %d,nItems %ld, Remain %ld\n",
2103              atype, aformat, cSelectionTargets, remain);
2104        /*
2105         * The TARGETS property should have returned us a list of atoms
2106         * corresponding to each selection target format supported.
2107         */
2108        if (atype == XA_ATOM || atype == x11drv_atom(TARGETS))
2109        {
2110            if (aformat == 32)
2111            {
2112                X11DRV_CLIPBOARD_InsertSelectionProperties(display, targetList, cSelectionTargets);
2113            }
2114            else if (aformat == 8)  /* work around quartz-wm brain damage */
2115            {
2116                unsigned long i, count = cSelectionTargets / sizeof(CARD32);
2117                Atom *atoms = HeapAlloc( GetProcessHeap(), 0, count * sizeof(Atom) );
2118                for (i = 0; i < count; i++)
2119                    atoms[i] = ((CARD32 *)targetList)[i];  /* FIXME: byte swapping */
2120                X11DRV_CLIPBOARD_InsertSelectionProperties( display, atoms, count );
2121                HeapFree( GetProcessHeap(), 0, atoms );
2122            }
2123        }
2124
2125        /* Free the list of targets */
2126        wine_tsx11_lock();
2127        XFree(targetList);
2128        wine_tsx11_unlock();
2129     }
2130
2131     return cSelectionTargets;
2132 }
2133
2134
2135 /**************************************************************************
2136  *      X11DRV_CLIPBOARD_ReadSelectionData
2137  *
2138  * This method is invoked only when we DO NOT own the X selection
2139  *
2140  * We always get the data from the selection client each time,
2141  * since we have no way of determining if the data in our cache is stale.
2142  */
2143 static BOOL X11DRV_CLIPBOARD_ReadSelectionData(Display *display, LPWINE_CLIPDATA lpData)
2144 {
2145     Bool res;
2146     DWORD i;
2147     XEvent xe;
2148     BOOL bRet = FALSE;
2149
2150     TRACE("%04x\n", lpData->wFormatID);
2151
2152     if (!lpData->lpFormat)
2153     {
2154         ERR("Requesting format %04x but no source format linked to data.\n",
2155             lpData->wFormatID);
2156         return FALSE;
2157     }
2158
2159     if (!selectionAcquired)
2160     {
2161         Window w = thread_selection_wnd();
2162         if(!w)
2163         {
2164             ERR("No window available to read selection data!\n");
2165             return FALSE;
2166         }
2167
2168         TRACE("Requesting conversion of %s property (%d) from selection type %08x\n",
2169             debugstr_w(lpData->lpFormat->Name), lpData->lpFormat->drvData, (UINT)selectionCacheSrc);
2170
2171         wine_tsx11_lock();
2172         XConvertSelection(display, selectionCacheSrc, lpData->lpFormat->drvData,
2173             x11drv_atom(SELECTION_DATA), w, CurrentTime);
2174         wine_tsx11_unlock();
2175
2176         /* wait until SelectionNotify is received */
2177         for (i = 0; i < SELECTION_RETRIES; i++)
2178         {
2179             wine_tsx11_lock();
2180             res = XCheckTypedWindowEvent(display, w, SelectionNotify, &xe);
2181             wine_tsx11_unlock();
2182             if (res && xe.xselection.selection == selectionCacheSrc) break;
2183
2184             usleep(SELECTION_WAIT);
2185         }
2186
2187         if (i == SELECTION_RETRIES)
2188         {
2189             ERR("Timed out waiting for SelectionNotify event\n");
2190         }
2191         /* Verify that the selection returned a valid TARGETS property */
2192         else if (xe.xselection.property != None)
2193         {
2194             /*
2195              *  Read the contents of the X selection property 
2196              *  into WINE's clipboard cache and converting the 
2197              *  data format if necessary.
2198              */
2199              HANDLE hData = lpData->lpFormat->lpDrvImportFunc(display, xe.xselection.requestor,
2200                  xe.xselection.property);
2201
2202              if (hData)
2203                  bRet = X11DRV_CLIPBOARD_InsertClipboardData(lpData->wFormatID, hData, 0, lpData->lpFormat, TRUE);
2204              else
2205                  TRACE("Import function failed\n");
2206         }
2207         else
2208         {
2209             TRACE("Failed to convert selection\n");
2210         }
2211     }
2212     else
2213     {
2214         ERR("Received request to cache selection data but process is owner\n");
2215     }
2216
2217     TRACE("Returning %d\n", bRet);
2218
2219     return bRet;
2220 }
2221
2222
2223 /**************************************************************************
2224  *              X11DRV_CLIPBOARD_GetProperty
2225  *  Gets type, data and size.
2226  */
2227 static BOOL X11DRV_CLIPBOARD_GetProperty(Display *display, Window w, Atom prop,
2228     Atom *atype, unsigned char** data, unsigned long* datasize)
2229 {
2230     int aformat;
2231     unsigned long pos = 0, nitems, remain, count;
2232     unsigned char *val = NULL, *buffer;
2233
2234     TRACE("Reading property %lu from X window %lx\n", prop, w);
2235
2236     for (;;)
2237     {
2238         wine_tsx11_lock();
2239         if (XGetWindowProperty(display, w, prop, pos, INT_MAX / 4, False,
2240                                AnyPropertyType, atype, &aformat, &nitems, &remain, &buffer) != Success)
2241         {
2242             wine_tsx11_unlock();
2243             WARN("Failed to read property\n");
2244             HeapFree( GetProcessHeap(), 0, val );
2245             return FALSE;
2246         }
2247
2248         count = get_property_size( aformat, nitems );
2249         if (!val) *data = HeapAlloc( GetProcessHeap(), 0, pos * sizeof(int) + count + 1 );
2250         else *data = HeapReAlloc( GetProcessHeap(), 0, val, pos * sizeof(int) + count + 1 );
2251
2252         if (!*data)
2253         {
2254             XFree( buffer );
2255             wine_tsx11_unlock();
2256             HeapFree( GetProcessHeap(), 0, val );
2257             return FALSE;
2258         }
2259         val = *data;
2260         memcpy( (int *)val + pos, buffer, count );
2261         XFree( buffer );
2262         wine_tsx11_unlock();
2263         if (!remain)
2264         {
2265             *datasize = pos * sizeof(int) + count;
2266             val[*datasize] = 0;
2267             break;
2268         }
2269         pos += count / sizeof(int);
2270     }
2271
2272     /* Delete the property on the window now that we are done
2273      * This will send a PropertyNotify event to the selection owner. */
2274     wine_tsx11_lock();
2275     XDeleteProperty(display, w, prop);
2276     wine_tsx11_unlock();
2277     return TRUE;
2278 }
2279
2280
2281 /**************************************************************************
2282  *              X11DRV_CLIPBOARD_ReadProperty
2283  *  Reads the contents of the X selection property.
2284  */
2285 static BOOL X11DRV_CLIPBOARD_ReadProperty(Display *display, Window w, Atom prop,
2286     unsigned char** data, unsigned long* datasize)
2287 {
2288     Atom atype;
2289     XEvent xe;
2290
2291     if (prop == None)
2292         return FALSE;
2293
2294     if (!X11DRV_CLIPBOARD_GetProperty(display, w, prop, &atype, data, datasize))
2295         return FALSE;
2296
2297     wine_tsx11_lock();
2298     while (XCheckTypedWindowEvent(display, w, PropertyNotify, &xe))
2299         ;
2300     wine_tsx11_unlock();
2301
2302     if (atype == x11drv_atom(INCR))
2303     {
2304         unsigned char *buf = *data;
2305         unsigned long bufsize = 0;
2306
2307         for (;;)
2308         {
2309             int i;
2310             unsigned char *prop_data, *tmp;
2311             unsigned long prop_size;
2312
2313             /* Wait until PropertyNotify is received */
2314             for (i = 0; i < SELECTION_RETRIES; i++)
2315             {
2316                 Bool res;
2317
2318                 wine_tsx11_lock();
2319                 res = XCheckTypedWindowEvent(display, w, PropertyNotify, &xe);
2320                 wine_tsx11_unlock();
2321                 if (res && xe.xproperty.atom == prop &&
2322                     xe.xproperty.state == PropertyNewValue)
2323                     break;
2324                 usleep(SELECTION_WAIT);
2325             }
2326
2327             if (i >= SELECTION_RETRIES ||
2328                 !X11DRV_CLIPBOARD_GetProperty(display, w, prop, &atype, &prop_data, &prop_size))
2329             {
2330                 HeapFree(GetProcessHeap(), 0, buf);
2331                 return FALSE;
2332             }
2333
2334             /* Retrieved entire data. */
2335             if (prop_size == 0)
2336             {
2337                 HeapFree(GetProcessHeap(), 0, prop_data);
2338                 *data = buf;
2339                 *datasize = bufsize;
2340                 return TRUE;
2341             }
2342
2343             tmp = HeapReAlloc(GetProcessHeap(), 0, buf, bufsize + prop_size + 1);
2344             if (!tmp)
2345             {
2346                 HeapFree(GetProcessHeap(), 0, buf);
2347                 return FALSE;
2348             }
2349
2350             buf = tmp;
2351             memcpy(buf + bufsize, prop_data, prop_size + 1);
2352             bufsize += prop_size;
2353             HeapFree(GetProcessHeap(), 0, prop_data);
2354         }
2355     }
2356
2357     return TRUE;
2358 }
2359
2360
2361 /**************************************************************************
2362  *              CLIPBOARD_SerializeMetafile
2363  */
2364 static HANDLE X11DRV_CLIPBOARD_SerializeMetafile(INT wformat, HANDLE hdata, LPDWORD lpcbytes, BOOL out)
2365 {
2366     HANDLE h = 0;
2367
2368     TRACE(" wFormat=%d hdata=%p out=%d\n", wformat, hdata, out);
2369
2370     if (out) /* Serialize out, caller should free memory */
2371     {
2372         *lpcbytes = 0; /* Assume failure */
2373
2374         if (wformat == CF_METAFILEPICT)
2375         {
2376             LPMETAFILEPICT lpmfp = GlobalLock(hdata);
2377             unsigned int size = GetMetaFileBitsEx(lpmfp->hMF, 0, NULL);
2378
2379             h = GlobalAlloc(0, size + sizeof(METAFILEPICT));
2380             if (h)
2381             {
2382                 char *pdata = GlobalLock(h);
2383
2384                 memcpy(pdata, lpmfp, sizeof(METAFILEPICT));
2385                 GetMetaFileBitsEx(lpmfp->hMF, size, pdata + sizeof(METAFILEPICT));
2386
2387                 *lpcbytes = size + sizeof(METAFILEPICT);
2388
2389                 GlobalUnlock(h);
2390             }
2391
2392             GlobalUnlock(hdata);
2393         }
2394         else if (wformat == CF_ENHMETAFILE)
2395         {
2396             int size = GetEnhMetaFileBits(hdata, 0, NULL);
2397
2398             h = GlobalAlloc(0, size);
2399             if (h)
2400             {
2401                 LPVOID pdata = GlobalLock(h);
2402
2403                 GetEnhMetaFileBits(hdata, size, pdata);
2404                 *lpcbytes = size;
2405
2406                 GlobalUnlock(h);
2407             }
2408         }
2409     }
2410     else
2411     {
2412         if (wformat == CF_METAFILEPICT)
2413         {
2414             h = GlobalAlloc(0, sizeof(METAFILEPICT));
2415             if (h)
2416             {
2417                 unsigned int wiresize, size;
2418                 LPMETAFILEPICT lpmfp = GlobalLock(h);
2419
2420                 memcpy(lpmfp, hdata, sizeof(METAFILEPICT));
2421                 wiresize = *lpcbytes - sizeof(METAFILEPICT);
2422                 lpmfp->hMF = SetMetaFileBitsEx(wiresize,
2423                     ((const BYTE *)hdata) + sizeof(METAFILEPICT));
2424                 size = GetMetaFileBitsEx(lpmfp->hMF, 0, NULL);
2425                 GlobalUnlock(h);
2426             }
2427         }
2428         else if (wformat == CF_ENHMETAFILE)
2429         {
2430             h = SetEnhMetaFileBits(*lpcbytes, hdata);
2431         }
2432     }
2433
2434     return h;
2435 }
2436
2437
2438 /**************************************************************************
2439  *              X11DRV_CLIPBOARD_ReleaseSelection
2440  *
2441  * Release XA_CLIPBOARD and XA_PRIMARY in response to a SelectionClear event.
2442  */
2443 static void X11DRV_CLIPBOARD_ReleaseSelection(Display *display, Atom selType, Window w, HWND hwnd, Time time)
2444 {
2445     /* w is the window that lost the selection
2446      */
2447     TRACE("event->window = %08x (selectionWindow = %08x) selectionAcquired=0x%08x\n",
2448           (unsigned)w, (unsigned)selectionWindow, (unsigned)selectionAcquired);
2449
2450     if (selectionAcquired && (w == selectionWindow))
2451     {
2452         CLIPBOARDINFO cbinfo;
2453
2454         /* completely give up the selection */
2455         TRACE("Lost CLIPBOARD (+PRIMARY) selection\n");
2456
2457         X11DRV_CLIPBOARD_GetClipboardInfo(&cbinfo);
2458
2459         if (cbinfo.flags & CB_PROCESS)
2460         {
2461             /* Since we're still the owner, this wasn't initiated by
2462                another Wine process */
2463             if (OpenClipboard(hwnd))
2464             {
2465                 /* Destroy private objects */
2466                 SendMessageW(cbinfo.hWndOwner, WM_DESTROYCLIPBOARD, 0, 0);
2467
2468                 /* Give up ownership of the windows clipboard */
2469                 X11DRV_CLIPBOARD_ReleaseOwnership();
2470                 CloseClipboard();
2471             }
2472         }
2473
2474         if ((selType == x11drv_atom(CLIPBOARD)) && (selectionAcquired & S_PRIMARY))
2475         {
2476             TRACE("Lost clipboard. Check if we need to release PRIMARY\n");
2477
2478             wine_tsx11_lock();
2479             if (selectionWindow == XGetSelectionOwner(display, XA_PRIMARY))
2480             {
2481                 TRACE("We still own PRIMARY. Releasing PRIMARY.\n");
2482                 XSetSelectionOwner(display, XA_PRIMARY, None, time);
2483             }
2484             else
2485                 TRACE("We no longer own PRIMARY\n");
2486             wine_tsx11_unlock();
2487         }
2488         else if ((selType == XA_PRIMARY) && (selectionAcquired & S_CLIPBOARD))
2489         {
2490             TRACE("Lost PRIMARY. Check if we need to release CLIPBOARD\n");
2491
2492             wine_tsx11_lock();
2493             if (selectionWindow == XGetSelectionOwner(display,x11drv_atom(CLIPBOARD)))
2494             {
2495                 TRACE("We still own CLIPBOARD. Releasing CLIPBOARD.\n");
2496                 XSetSelectionOwner(display, x11drv_atom(CLIPBOARD), None, time);
2497             }
2498             else
2499                 TRACE("We no longer own CLIPBOARD\n");
2500             wine_tsx11_unlock();
2501         }
2502
2503         selectionWindow = None;
2504
2505         X11DRV_EmptyClipboard(FALSE);
2506
2507         /* Reset the selection flags now that we are done */
2508         selectionAcquired = S_NOSELECTION;
2509     }
2510 }
2511
2512
2513 /**************************************************************************
2514  *              IsSelectionOwner (X11DRV.@)
2515  *
2516  * Returns: TRUE if the selection is owned by this process, FALSE otherwise
2517  */
2518 static BOOL X11DRV_CLIPBOARD_IsSelectionOwner(void)
2519 {
2520     return selectionAcquired;
2521 }
2522
2523
2524 /**************************************************************************
2525  *                X11DRV Clipboard Exports
2526  **************************************************************************/
2527
2528
2529 /**************************************************************************
2530  *              RegisterClipboardFormat (X11DRV.@)
2531  *
2532  * Registers a custom X clipboard format
2533  * Returns: Format id or 0 on failure
2534  */
2535 UINT CDECL X11DRV_RegisterClipboardFormat(LPCWSTR FormatName)
2536 {
2537     LPWINE_CLIPFORMAT lpFormat;
2538
2539     if (FormatName == NULL) return 0;
2540     if (!(lpFormat = register_format( FormatName, 0 ))) return 0;
2541     return lpFormat->wFormatID;
2542 }
2543
2544
2545 /**************************************************************************
2546  *              X11DRV_GetClipboardFormatName
2547  */
2548 INT CDECL X11DRV_GetClipboardFormatName(UINT wFormat, LPWSTR retStr, INT maxlen)
2549 {
2550     LPWINE_CLIPFORMAT lpFormat;
2551
2552     TRACE("(%04X, %p, %d) !\n", wFormat, retStr, maxlen);
2553
2554     if (wFormat < 0xc000)
2555     {
2556         SetLastError(ERROR_INVALID_PARAMETER);
2557         return 0;
2558     }
2559
2560     lpFormat = X11DRV_CLIPBOARD_LookupFormat(wFormat);
2561
2562     if (!lpFormat || (lpFormat->wFlags & CF_FLAG_BUILTINFMT))
2563     {
2564         TRACE("Unknown format 0x%08x!\n", wFormat);
2565         SetLastError(ERROR_INVALID_HANDLE);
2566         return 0;
2567     }
2568
2569     lstrcpynW(retStr, lpFormat->Name, maxlen);
2570
2571     return strlenW(retStr);
2572 }
2573
2574 static void selection_acquire(void)
2575 {
2576     Window owner;
2577     Display *display;
2578
2579     owner = thread_selection_wnd();
2580     display = thread_display();
2581
2582     wine_tsx11_lock();
2583
2584     selectionAcquired = 0;
2585     selectionWindow = 0;
2586
2587     /* Grab PRIMARY selection if not owned */
2588     if (use_primary_selection)
2589         XSetSelectionOwner(display, XA_PRIMARY, owner, CurrentTime);
2590
2591     /* Grab CLIPBOARD selection if not owned */
2592     XSetSelectionOwner(display, x11drv_atom(CLIPBOARD), owner, CurrentTime);
2593
2594     if (use_primary_selection && XGetSelectionOwner(display, XA_PRIMARY) == owner)
2595         selectionAcquired |= S_PRIMARY;
2596
2597     if (XGetSelectionOwner(display,x11drv_atom(CLIPBOARD)) == owner)
2598         selectionAcquired |= S_CLIPBOARD;
2599
2600     wine_tsx11_unlock();
2601
2602     if (selectionAcquired)
2603     {
2604         selectionWindow = owner;
2605         TRACE("Grabbed X selection, owner=(%08x)\n", (unsigned) owner);
2606     }
2607 }
2608
2609 static DWORD WINAPI selection_thread_proc(LPVOID p)
2610 {
2611     HANDLE event = p;
2612
2613     TRACE("\n");
2614
2615     selection_acquire();
2616     SetEvent(event);
2617
2618     while (selectionAcquired)
2619     {
2620         MsgWaitForMultipleObjectsEx(0, NULL, INFINITE, QS_SENDMESSAGE, 0);
2621     }
2622
2623     return 0;
2624 }
2625
2626 /**************************************************************************
2627  *              AcquireClipboard (X11DRV.@)
2628  */
2629 int CDECL X11DRV_AcquireClipboard(HWND hWndClipWindow)
2630 {
2631     DWORD procid;
2632     HANDLE selectionThread;
2633
2634     TRACE(" %p\n", hWndClipWindow);
2635
2636     /*
2637      * It's important that the selection get acquired from the thread
2638      * that owns the clipboard window. The primary reason is that we know 
2639      * it is running a message loop and therefore can process the 
2640      * X selection events.
2641      */
2642     if (hWndClipWindow &&
2643         GetCurrentThreadId() != GetWindowThreadProcessId(hWndClipWindow, &procid))
2644     {
2645         if (procid != GetCurrentProcessId())
2646         {
2647             WARN("Setting clipboard owner to other process is not supported\n");
2648             hWndClipWindow = NULL;
2649         }
2650         else
2651         {
2652             TRACE("Thread %x is acquiring selection with thread %x's window %p\n",
2653                 GetCurrentThreadId(),
2654                 GetWindowThreadProcessId(hWndClipWindow, NULL), hWndClipWindow);
2655
2656             return SendMessageW(hWndClipWindow, WM_X11DRV_ACQUIRE_SELECTION, 0, 0);
2657         }
2658     }
2659
2660     if (hWndClipWindow)
2661     {
2662         selection_acquire();
2663     }
2664     else
2665     {
2666         HANDLE event = CreateEventW(NULL, FALSE, FALSE, NULL);
2667         selectionThread = CreateThread(NULL, 0, &selection_thread_proc, event, 0, NULL);
2668
2669         if (!selectionThread)
2670         {
2671             WARN("Could not start clipboard thread\n");
2672             return 0;
2673         }
2674
2675         WaitForSingleObject(event, INFINITE);
2676         CloseHandle(event);
2677         CloseHandle(selectionThread);
2678     }
2679
2680     return 1;
2681 }
2682
2683
2684 /**************************************************************************
2685  *      X11DRV_EmptyClipboard
2686  *
2687  * Empty cached clipboard data. 
2688  */
2689 void CDECL X11DRV_EmptyClipboard(BOOL keepunowned)
2690 {
2691     if (ClipData)
2692     {
2693         LPWINE_CLIPDATA lpData, lpStart;
2694         LPWINE_CLIPDATA lpNext = ClipData;
2695
2696         TRACE(" called with %d entries in cache.\n", ClipDataCount);
2697
2698         do
2699         {
2700             lpStart = ClipData;
2701             lpData = lpNext;
2702             lpNext = lpData->NextData;
2703
2704             if (!keepunowned || !(lpData->wFlags & CF_FLAG_UNOWNED))
2705             {
2706             lpData->PrevData->NextData = lpData->NextData;
2707             lpData->NextData->PrevData = lpData->PrevData;
2708
2709                 if (lpData == ClipData)
2710                     ClipData = lpNext != lpData ? lpNext : NULL;
2711
2712             X11DRV_CLIPBOARD_FreeData(lpData);
2713             HeapFree(GetProcessHeap(), 0, lpData);
2714
2715                 ClipDataCount--;
2716             }
2717         } while (lpNext != lpStart);
2718     }
2719
2720     TRACE(" %d entries remaining in cache.\n", ClipDataCount);
2721 }
2722
2723
2724
2725 /**************************************************************************
2726  *              X11DRV_SetClipboardData
2727  */
2728 BOOL CDECL X11DRV_SetClipboardData(UINT wFormat, HANDLE hData, BOOL owner)
2729 {
2730     DWORD flags = 0;
2731     BOOL bResult = TRUE;
2732
2733     /* If it's not owned, data can only be set if the format data is not already owned
2734        and its rendering is not delayed */
2735     if (!owner)
2736     {
2737         CLIPBOARDINFO cbinfo;
2738         LPWINE_CLIPDATA lpRender;
2739
2740         X11DRV_CLIPBOARD_UpdateCache(&cbinfo);
2741
2742         if (!hData ||
2743             ((lpRender = X11DRV_CLIPBOARD_LookupData(wFormat)) &&
2744             !(lpRender->wFlags & CF_FLAG_UNOWNED)))
2745             bResult = FALSE;
2746         else
2747             flags = CF_FLAG_UNOWNED;
2748     }
2749
2750     bResult &= X11DRV_CLIPBOARD_InsertClipboardData(wFormat, hData, flags, NULL, TRUE);
2751
2752     return bResult;
2753 }
2754
2755
2756 /**************************************************************************
2757  *              CountClipboardFormats
2758  */
2759 INT CDECL X11DRV_CountClipboardFormats(void)
2760 {
2761     CLIPBOARDINFO cbinfo;
2762
2763     X11DRV_CLIPBOARD_UpdateCache(&cbinfo);
2764
2765     TRACE(" count=%d\n", ClipDataCount);
2766
2767     return ClipDataCount;
2768 }
2769
2770
2771 /**************************************************************************
2772  *              X11DRV_EnumClipboardFormats
2773  */
2774 UINT CDECL X11DRV_EnumClipboardFormats(UINT wFormat)
2775 {
2776     CLIPBOARDINFO cbinfo;
2777     UINT wNextFormat = 0;
2778
2779     TRACE("(%04X)\n", wFormat);
2780
2781     X11DRV_CLIPBOARD_UpdateCache(&cbinfo);
2782
2783     if (!wFormat)
2784     {
2785         if (ClipData)
2786             wNextFormat = ClipData->wFormatID;
2787     }
2788     else
2789     {
2790         LPWINE_CLIPDATA lpData = X11DRV_CLIPBOARD_LookupData(wFormat);
2791
2792         if (lpData && lpData->NextData != ClipData)
2793             wNextFormat = lpData->NextData->wFormatID;
2794     }
2795
2796     return wNextFormat;
2797 }
2798
2799
2800 /**************************************************************************
2801  *              X11DRV_IsClipboardFormatAvailable
2802  */
2803 BOOL CDECL X11DRV_IsClipboardFormatAvailable(UINT wFormat)
2804 {
2805     BOOL bRet = FALSE;
2806     CLIPBOARDINFO cbinfo;
2807
2808     TRACE("(%04X)\n", wFormat);
2809
2810     X11DRV_CLIPBOARD_UpdateCache(&cbinfo);
2811
2812     if (wFormat != 0 && X11DRV_CLIPBOARD_LookupData(wFormat))
2813         bRet = TRUE;
2814
2815     TRACE("(%04X)- ret(%d)\n", wFormat, bRet);
2816
2817     return bRet;
2818 }
2819
2820
2821 /**************************************************************************
2822  *              GetClipboardData (USER.142)
2823  */
2824 HANDLE CDECL X11DRV_GetClipboardData(UINT wFormat)
2825 {
2826     CLIPBOARDINFO cbinfo;
2827     LPWINE_CLIPDATA lpRender;
2828
2829     TRACE("(%04X)\n", wFormat);
2830
2831     X11DRV_CLIPBOARD_UpdateCache(&cbinfo);
2832
2833     if ((lpRender = X11DRV_CLIPBOARD_LookupData(wFormat)))
2834     {
2835         if ( !lpRender->hData )
2836             X11DRV_CLIPBOARD_RenderFormat(thread_init_display(), lpRender);
2837
2838         TRACE(" returning %p (type %04x)\n", lpRender->hData, lpRender->wFormatID);
2839         return lpRender->hData;
2840     }
2841
2842     return 0;
2843 }
2844
2845
2846 /**************************************************************************
2847  *              ResetSelectionOwner
2848  *
2849  * Called when the thread owning the selection is destroyed and we need to
2850  * preserve the selection ownership. We look for another top level window
2851  * in this process and send it a message to acquire the selection.
2852  */
2853 void X11DRV_ResetSelectionOwner(void)
2854 {
2855     HWND hwnd;
2856     DWORD procid;
2857
2858     TRACE("\n");
2859
2860     if (!selectionAcquired  || thread_selection_wnd() != selectionWindow)
2861         return;
2862
2863     selectionAcquired = S_NOSELECTION;
2864     selectionWindow = 0;
2865
2866     hwnd = GetWindow(GetDesktopWindow(), GW_CHILD);
2867     do
2868     {
2869         if (GetCurrentThreadId() != GetWindowThreadProcessId(hwnd, &procid))
2870         {
2871             if (GetCurrentProcessId() == procid)
2872             {
2873                 if (SendMessageW(hwnd, WM_X11DRV_ACQUIRE_SELECTION, 0, 0))
2874                     return;
2875             }
2876         }
2877     } while ((hwnd = GetWindow(hwnd, GW_HWNDNEXT)) != NULL);
2878
2879     WARN("Failed to find another thread to take selection ownership. Clipboard data will be lost.\n");
2880
2881     X11DRV_CLIPBOARD_ReleaseOwnership();
2882     X11DRV_EmptyClipboard(FALSE);
2883 }
2884
2885
2886 /**************************************************************************
2887  *                      X11DRV_CLIPBOARD_SynthesizeData
2888  */
2889 static BOOL X11DRV_CLIPBOARD_SynthesizeData(UINT wFormatID)
2890 {
2891     BOOL bsyn = TRUE;
2892     LPWINE_CLIPDATA lpSource = NULL;
2893
2894     TRACE(" %04x\n", wFormatID);
2895
2896     /* Don't need to synthesize if it already exists */
2897     if (X11DRV_CLIPBOARD_LookupData(wFormatID))
2898         return TRUE;
2899
2900     if (wFormatID == CF_UNICODETEXT || wFormatID == CF_TEXT || wFormatID == CF_OEMTEXT)
2901     {
2902         bsyn = ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_UNICODETEXT)) &&
2903             ~lpSource->wFlags & CF_FLAG_SYNTHESIZED) ||
2904             ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_TEXT)) &&
2905             ~lpSource->wFlags & CF_FLAG_SYNTHESIZED) ||
2906             ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_OEMTEXT)) &&
2907             ~lpSource->wFlags & CF_FLAG_SYNTHESIZED);
2908     }
2909     else if (wFormatID == CF_ENHMETAFILE)
2910     {
2911         bsyn = (lpSource = X11DRV_CLIPBOARD_LookupData(CF_METAFILEPICT)) &&
2912             ~lpSource->wFlags & CF_FLAG_SYNTHESIZED;
2913     }
2914     else if (wFormatID == CF_METAFILEPICT)
2915     {
2916         bsyn = (lpSource = X11DRV_CLIPBOARD_LookupData(CF_ENHMETAFILE)) &&
2917             ~lpSource->wFlags & CF_FLAG_SYNTHESIZED;
2918     }
2919     else if (wFormatID == CF_DIB)
2920     {
2921         bsyn = (lpSource = X11DRV_CLIPBOARD_LookupData(CF_BITMAP)) &&
2922             ~lpSource->wFlags & CF_FLAG_SYNTHESIZED;
2923     }
2924     else if (wFormatID == CF_BITMAP)
2925     {
2926         bsyn = (lpSource = X11DRV_CLIPBOARD_LookupData(CF_DIB)) &&
2927             ~lpSource->wFlags & CF_FLAG_SYNTHESIZED;
2928     }
2929
2930     if (bsyn)
2931         X11DRV_CLIPBOARD_InsertClipboardData(wFormatID, 0, CF_FLAG_SYNTHESIZED, NULL, TRUE);
2932
2933     return bsyn;
2934 }
2935
2936
2937
2938 /**************************************************************************
2939  *              X11DRV_EndClipboardUpdate
2940  * TODO:
2941  *  Add locale if it hasn't already been added
2942  */
2943 void CDECL X11DRV_EndClipboardUpdate(void)
2944 {
2945     INT count = ClipDataCount;
2946
2947     /* Do Unicode <-> Text <-> OEM mapping */
2948     X11DRV_CLIPBOARD_SynthesizeData(CF_TEXT);
2949     X11DRV_CLIPBOARD_SynthesizeData(CF_OEMTEXT);
2950     X11DRV_CLIPBOARD_SynthesizeData(CF_UNICODETEXT);
2951
2952     /* Enhmetafile <-> MetafilePict mapping */
2953     X11DRV_CLIPBOARD_SynthesizeData(CF_ENHMETAFILE);
2954     X11DRV_CLIPBOARD_SynthesizeData(CF_METAFILEPICT);
2955
2956     /* DIB <-> Bitmap mapping */
2957     X11DRV_CLIPBOARD_SynthesizeData(CF_DIB);
2958     X11DRV_CLIPBOARD_SynthesizeData(CF_BITMAP);
2959
2960     TRACE("%d formats added to cached data\n", ClipDataCount - count);
2961 }
2962
2963
2964 /***********************************************************************
2965  *           X11DRV_SelectionRequest_TARGETS
2966  *  Service a TARGETS selection request event
2967  */
2968 static Atom X11DRV_SelectionRequest_TARGETS( Display *display, Window requestor,
2969                                              Atom target, Atom rprop )
2970 {
2971     UINT i;
2972     Atom* targets;
2973     ULONG cTargets;
2974     LPWINE_CLIPFORMAT lpFormats;
2975     LPWINE_CLIPDATA lpData;
2976
2977     /* Create X atoms for any clipboard types which don't have atoms yet.
2978      * This avoids sending bogus zero atoms.
2979      * Without this, copying might not have access to all clipboard types.
2980      * FIXME: is it safe to call this here?
2981      */
2982     intern_atoms();
2983
2984     /*
2985      * Count the number of items we wish to expose as selection targets.
2986      */
2987     cTargets = 1; /* Include TARGETS */
2988
2989     if (!(lpData = ClipData)) return None;
2990
2991     do
2992     {
2993         lpFormats = ClipFormats;
2994
2995         while (lpFormats)
2996         {
2997             if ((lpFormats->wFormatID == lpData->wFormatID) &&
2998                 lpFormats->lpDrvExportFunc && lpFormats->drvData)
2999                 cTargets++;
3000
3001             lpFormats = lpFormats->NextFormat;
3002         }
3003
3004         lpData = lpData->NextData;
3005     }
3006     while (lpData != ClipData);
3007
3008     TRACE(" found %d formats\n", cTargets);
3009
3010     /* Allocate temp buffer */
3011     targets = HeapAlloc( GetProcessHeap(), 0, cTargets * sizeof(Atom));
3012     if(targets == NULL)
3013         return None;
3014
3015     i = 0;
3016     lpData = ClipData;
3017     targets[i++] = x11drv_atom(TARGETS);
3018
3019     do
3020     {
3021         lpFormats = ClipFormats;
3022
3023         while (lpFormats)
3024         {
3025             if ((lpFormats->wFormatID == lpData->wFormatID) &&
3026                 lpFormats->lpDrvExportFunc && lpFormats->drvData)
3027                 targets[i++] = lpFormats->drvData;
3028
3029             lpFormats = lpFormats->NextFormat;
3030         }
3031
3032         lpData = lpData->NextData;
3033     }
3034     while (lpData != ClipData);
3035
3036     wine_tsx11_lock();
3037
3038     if (TRACE_ON(clipboard))
3039     {
3040         unsigned int i;
3041         for ( i = 0; i < cTargets; i++)
3042         {
3043             char *itemFmtName = XGetAtomName(display, targets[i]);
3044             TRACE("\tAtom# %d:  Property %ld Type %s\n", i, targets[i], itemFmtName);
3045             XFree(itemFmtName);
3046         }
3047     }
3048
3049     /* We may want to consider setting the type to xaTargets instead,
3050      * in case some apps expect this instead of XA_ATOM */
3051     XChangeProperty(display, requestor, rprop, XA_ATOM, 32,
3052                     PropModeReplace, (unsigned char *)targets, cTargets);
3053     wine_tsx11_unlock();
3054
3055     HeapFree(GetProcessHeap(), 0, targets);
3056
3057     return rprop;
3058 }
3059
3060
3061 /***********************************************************************
3062  *           X11DRV_SelectionRequest_MULTIPLE
3063  *  Service a MULTIPLE selection request event
3064  *  rprop contains a list of (target,property) atom pairs.
3065  *  The first atom names a target and the second names a property.
3066  *  The effect is as if we have received a sequence of SelectionRequest events
3067  *  (one for each atom pair) except that:
3068  *  1. We reply with a SelectionNotify only when all the requested conversions
3069  *  have been performed.
3070  *  2. If we fail to convert the target named by an atom in the MULTIPLE property,
3071  *  we replace the atom in the property by None.
3072  */
3073 static Atom X11DRV_SelectionRequest_MULTIPLE( HWND hWnd, XSelectionRequestEvent *pevent )
3074 {
3075     Display *display = pevent->display;
3076     Atom           rprop;
3077     Atom           atype=AnyPropertyType;
3078     int            aformat;
3079     unsigned long  remain;
3080     Atom*          targetPropList=NULL;
3081     unsigned long  cTargetPropList = 0;
3082
3083     /* If the specified property is None the requestor is an obsolete client.
3084      * We support these by using the specified target atom as the reply property.
3085      */
3086     rprop = pevent->property;
3087     if( rprop == None )
3088         rprop = pevent->target;
3089     if (!rprop)
3090         return 0;
3091
3092     /* Read the MULTIPLE property contents. This should contain a list of
3093      * (target,property) atom pairs.
3094      */
3095     wine_tsx11_lock();
3096     if(XGetWindowProperty(display, pevent->requestor, rprop,
3097                           0, 0x3FFF, False, AnyPropertyType, &atype,&aformat,
3098                           &cTargetPropList, &remain,
3099                           (unsigned char**)&targetPropList) != Success)
3100     {
3101         wine_tsx11_unlock();
3102         TRACE("\tCouldn't read MULTIPLE property\n");
3103     }
3104     else
3105     {
3106         TRACE("\tType %s,Format %d,nItems %ld, Remain %ld\n",
3107               XGetAtomName(display, atype), aformat, cTargetPropList, remain);
3108         wine_tsx11_unlock();
3109
3110         /*
3111          * Make sure we got what we expect.
3112          * NOTE: According to the X-ICCCM Version 2.0 documentation the property sent
3113          * in a MULTIPLE selection request should be of type ATOM_PAIR.
3114          * However some X apps(such as XPaint) are not compliant with this and return
3115          * a user defined atom in atype when XGetWindowProperty is called.
3116          * The data *is* an atom pair but is not denoted as such.
3117          */
3118         if(aformat == 32 /* atype == xAtomPair */ )
3119         {
3120             unsigned int i;
3121
3122             /* Iterate through the ATOM_PAIR list and execute a SelectionRequest
3123              * for each (target,property) pair */
3124
3125             for (i = 0; i < cTargetPropList; i+=2)
3126             {
3127                 XSelectionRequestEvent event;
3128
3129                 if (TRACE_ON(clipboard))
3130                 {
3131                     char *targetName, *propName;
3132                     wine_tsx11_lock();
3133                     targetName = XGetAtomName(display, targetPropList[i]);
3134                     propName = XGetAtomName(display, targetPropList[i+1]);
3135                     TRACE("MULTIPLE(%d): Target='%s' Prop='%s'\n",
3136                           i/2, targetName, propName);
3137                     XFree(targetName);
3138                     XFree(propName);
3139                     wine_tsx11_unlock();
3140                 }
3141
3142                 /* We must have a non "None" property to service a MULTIPLE target atom */
3143                 if ( !targetPropList[i+1] )
3144                 {
3145                     TRACE("\tMULTIPLE(%d): Skipping target with empty property!\n", i);
3146                     continue;
3147                 }
3148
3149                 /* Set up an XSelectionRequestEvent for this (target,property) pair */
3150                 event = *pevent;
3151                 event.target = targetPropList[i];
3152                 event.property = targetPropList[i+1];
3153
3154                 /* Fire a SelectionRequest, informing the handler that we are processing
3155                  * a MULTIPLE selection request event.
3156                  */
3157                 X11DRV_HandleSelectionRequest( hWnd, &event, TRUE );
3158             }
3159         }
3160
3161         /* Free the list of targets/properties */
3162         wine_tsx11_lock();
3163         XFree(targetPropList);
3164         wine_tsx11_unlock();
3165     }
3166
3167     return rprop;
3168 }
3169
3170
3171 /***********************************************************************
3172  *           X11DRV_HandleSelectionRequest
3173  *  Process an event selection request event.
3174  *  The bIsMultiple flag is used to signal when EVENT_SelectionRequest is called
3175  *  recursively while servicing a "MULTIPLE" selection target.
3176  *
3177  *  Note: We only receive this event when WINE owns the X selection
3178  */
3179 static void X11DRV_HandleSelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple )
3180 {
3181     Display *display = event->display;
3182     XSelectionEvent result;
3183     Atom rprop = None;
3184     Window request = event->requestor;
3185
3186     TRACE("\n");
3187
3188     /*
3189      * We can only handle the selection request if :
3190      * The selection is PRIMARY or CLIPBOARD, AND we can successfully open the clipboard.
3191      * Don't do these checks or open the clipboard while recursively processing MULTIPLE,
3192      * since this has been already done.
3193      */
3194     if ( !bIsMultiple )
3195     {
3196         if (((event->selection != XA_PRIMARY) && (event->selection != x11drv_atom(CLIPBOARD))))
3197             goto END;
3198     }
3199
3200     /* If the specified property is None the requestor is an obsolete client.
3201      * We support these by using the specified target atom as the reply property.
3202      */
3203     rprop = event->property;
3204     if( rprop == None )
3205         rprop = event->target;
3206
3207     if(event->target == x11drv_atom(TARGETS))  /*  Return a list of all supported targets */
3208     {
3209         /* TARGETS selection request */
3210         rprop = X11DRV_SelectionRequest_TARGETS( display, request, event->target, rprop );
3211     }
3212     else if(event->target == x11drv_atom(MULTIPLE))  /*  rprop contains a list of (target, property) atom pairs */
3213     {
3214         /* MULTIPLE selection request */
3215         rprop = X11DRV_SelectionRequest_MULTIPLE( hWnd, event );
3216     }
3217     else
3218     {
3219         LPWINE_CLIPFORMAT lpFormat = X11DRV_CLIPBOARD_LookupProperty(NULL, event->target);
3220
3221         if (lpFormat && lpFormat->lpDrvExportFunc)
3222         {
3223             LPWINE_CLIPDATA lpData = X11DRV_CLIPBOARD_LookupData(lpFormat->wFormatID);
3224
3225             if (lpData)
3226             {
3227                 unsigned char* lpClipData;
3228                 DWORD cBytes;
3229                 HANDLE hClipData = lpFormat->lpDrvExportFunc(display, request, event->target,
3230                                                              rprop, lpData, &cBytes);
3231
3232                 if (hClipData && (lpClipData = GlobalLock(hClipData)))
3233                 {
3234                     TRACE("\tUpdating property %s, %d bytes\n", debugstr_w(lpFormat->Name), cBytes);
3235
3236                     wine_tsx11_lock();
3237                     XChangeProperty(display, request, rprop, event->target,
3238                                     8, PropModeReplace, lpClipData, cBytes);
3239                     wine_tsx11_unlock();
3240
3241                     GlobalUnlock(hClipData);
3242                     GlobalFree(hClipData);
3243                 }
3244             }
3245         }
3246     }
3247
3248 END:
3249     /* reply to sender
3250      * SelectionNotify should be sent only at the end of a MULTIPLE request
3251      */
3252     if ( !bIsMultiple )
3253     {
3254         result.type = SelectionNotify;
3255         result.display = display;
3256         result.requestor = request;
3257         result.selection = event->selection;
3258         result.property = rprop;
3259         result.target = event->target;
3260         result.time = event->time;
3261         TRACE("Sending SelectionNotify event...\n");
3262         wine_tsx11_lock();
3263         XSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
3264         wine_tsx11_unlock();
3265     }
3266 }
3267
3268
3269 /***********************************************************************
3270  *           X11DRV_SelectionRequest
3271  */
3272 void X11DRV_SelectionRequest( HWND hWnd, XEvent *event )
3273 {
3274     X11DRV_HandleSelectionRequest( hWnd, &event->xselectionrequest, FALSE );
3275 }
3276
3277
3278 /***********************************************************************
3279  *           X11DRV_SelectionClear
3280  */
3281 void X11DRV_SelectionClear( HWND hWnd, XEvent *xev )
3282 {
3283     XSelectionClearEvent *event = &xev->xselectionclear;
3284     if (event->selection == XA_PRIMARY || event->selection == x11drv_atom(CLIPBOARD))
3285         X11DRV_CLIPBOARD_ReleaseSelection( event->display, event->selection,
3286                                            event->window, hWnd, event->time );
3287 }
3288
3289 /***********************************************************************
3290  *           X11DRV_Clipboard_Cleanup
3291  */
3292 void X11DRV_Clipboard_Cleanup(void)
3293 {
3294     selectionAcquired = S_NOSELECTION;
3295
3296     X11DRV_EmptyClipboard(FALSE);
3297 }