wininet: Handle proxy entries of the form <proto>=<proxy>, and allow multiple proxies.
[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              bRet = X11DRV_CLIPBOARD_InsertClipboardData(lpData->wFormatID, hData, 0, lpData->lpFormat, TRUE);
2203         }
2204         else
2205         {
2206             TRACE("Failed to convert selection\n");
2207         }
2208     }
2209     else
2210     {
2211         ERR("Received request to cache selection data but process is owner\n");
2212     }
2213
2214     TRACE("Returning %d\n", bRet);
2215
2216     return bRet;
2217 }
2218
2219
2220 /**************************************************************************
2221  *              X11DRV_CLIPBOARD_GetProperty
2222  *  Gets type, data and size.
2223  */
2224 static BOOL X11DRV_CLIPBOARD_GetProperty(Display *display, Window w, Atom prop,
2225     Atom *atype, unsigned char** data, unsigned long* datasize)
2226 {
2227     int aformat;
2228     unsigned long pos = 0, nitems, remain, count;
2229     unsigned char *val = NULL, *buffer;
2230
2231     TRACE("Reading property %lu from X window %lx\n", prop, w);
2232
2233     for (;;)
2234     {
2235         wine_tsx11_lock();
2236         if (XGetWindowProperty(display, w, prop, pos, INT_MAX / 4, False,
2237                                AnyPropertyType, atype, &aformat, &nitems, &remain, &buffer) != Success)
2238         {
2239             wine_tsx11_unlock();
2240             WARN("Failed to read property\n");
2241             HeapFree( GetProcessHeap(), 0, val );
2242             return FALSE;
2243         }
2244
2245         count = get_property_size( aformat, nitems );
2246         if (!val) *data = HeapAlloc( GetProcessHeap(), 0, pos * sizeof(int) + count + 1 );
2247         else *data = HeapReAlloc( GetProcessHeap(), 0, val, pos * sizeof(int) + count + 1 );
2248
2249         if (!*data)
2250         {
2251             XFree( buffer );
2252             wine_tsx11_unlock();
2253             HeapFree( GetProcessHeap(), 0, val );
2254             return FALSE;
2255         }
2256         val = *data;
2257         memcpy( (int *)val + pos, buffer, count );
2258         XFree( buffer );
2259         wine_tsx11_unlock();
2260         if (!remain)
2261         {
2262             *datasize = pos * sizeof(int) + count;
2263             val[*datasize] = 0;
2264             break;
2265         }
2266         pos += count / sizeof(int);
2267     }
2268
2269     /* Delete the property on the window now that we are done
2270      * This will send a PropertyNotify event to the selection owner. */
2271     wine_tsx11_lock();
2272     XDeleteProperty(display, w, prop);
2273     wine_tsx11_unlock();
2274     return TRUE;
2275 }
2276
2277
2278 /**************************************************************************
2279  *              X11DRV_CLIPBOARD_ReadProperty
2280  *  Reads the contents of the X selection property.
2281  */
2282 static BOOL X11DRV_CLIPBOARD_ReadProperty(Display *display, Window w, Atom prop,
2283     unsigned char** data, unsigned long* datasize)
2284 {
2285     Atom atype;
2286     XEvent xe;
2287
2288     if (prop == None)
2289         return FALSE;
2290
2291     if (!X11DRV_CLIPBOARD_GetProperty(display, w, prop, &atype, data, datasize))
2292         return FALSE;
2293
2294     wine_tsx11_lock();
2295     while (XCheckTypedWindowEvent(display, w, PropertyNotify, &xe))
2296         ;
2297     wine_tsx11_unlock();
2298
2299     if (atype == x11drv_atom(INCR))
2300     {
2301         unsigned char *buf = *data;
2302         unsigned long bufsize = 0;
2303
2304         for (;;)
2305         {
2306             int i;
2307             unsigned char *prop_data, *tmp;
2308             unsigned long prop_size;
2309
2310             /* Wait until PropertyNotify is received */
2311             for (i = 0; i < SELECTION_RETRIES; i++)
2312             {
2313                 Bool res;
2314
2315                 wine_tsx11_lock();
2316                 res = XCheckTypedWindowEvent(display, w, PropertyNotify, &xe);
2317                 wine_tsx11_unlock();
2318                 if (res && xe.xproperty.atom == prop &&
2319                     xe.xproperty.state == PropertyNewValue)
2320                     break;
2321                 usleep(SELECTION_WAIT);
2322             }
2323
2324             if (i >= SELECTION_RETRIES ||
2325                 !X11DRV_CLIPBOARD_GetProperty(display, w, prop, &atype, &prop_data, &prop_size))
2326             {
2327                 HeapFree(GetProcessHeap(), 0, buf);
2328                 return FALSE;
2329             }
2330
2331             /* Retrieved entire data. */
2332             if (prop_size == 0)
2333             {
2334                 HeapFree(GetProcessHeap(), 0, prop_data);
2335                 *data = buf;
2336                 *datasize = bufsize;
2337                 return TRUE;
2338             }
2339
2340             tmp = HeapReAlloc(GetProcessHeap(), 0, buf, bufsize + prop_size + 1);
2341             if (!tmp)
2342             {
2343                 HeapFree(GetProcessHeap(), 0, buf);
2344                 return FALSE;
2345             }
2346
2347             buf = tmp;
2348             memcpy(buf + bufsize, prop_data, prop_size + 1);
2349             bufsize += prop_size;
2350             HeapFree(GetProcessHeap(), 0, prop_data);
2351         }
2352     }
2353
2354     return TRUE;
2355 }
2356
2357
2358 /**************************************************************************
2359  *              CLIPBOARD_SerializeMetafile
2360  */
2361 static HANDLE X11DRV_CLIPBOARD_SerializeMetafile(INT wformat, HANDLE hdata, LPDWORD lpcbytes, BOOL out)
2362 {
2363     HANDLE h = 0;
2364
2365     TRACE(" wFormat=%d hdata=%p out=%d\n", wformat, hdata, out);
2366
2367     if (out) /* Serialize out, caller should free memory */
2368     {
2369         *lpcbytes = 0; /* Assume failure */
2370
2371         if (wformat == CF_METAFILEPICT)
2372         {
2373             LPMETAFILEPICT lpmfp = GlobalLock(hdata);
2374             unsigned int size = GetMetaFileBitsEx(lpmfp->hMF, 0, NULL);
2375
2376             h = GlobalAlloc(0, size + sizeof(METAFILEPICT));
2377             if (h)
2378             {
2379                 char *pdata = GlobalLock(h);
2380
2381                 memcpy(pdata, lpmfp, sizeof(METAFILEPICT));
2382                 GetMetaFileBitsEx(lpmfp->hMF, size, pdata + sizeof(METAFILEPICT));
2383
2384                 *lpcbytes = size + sizeof(METAFILEPICT);
2385
2386                 GlobalUnlock(h);
2387             }
2388
2389             GlobalUnlock(hdata);
2390         }
2391         else if (wformat == CF_ENHMETAFILE)
2392         {
2393             int size = GetEnhMetaFileBits(hdata, 0, NULL);
2394
2395             h = GlobalAlloc(0, size);
2396             if (h)
2397             {
2398                 LPVOID pdata = GlobalLock(h);
2399
2400                 GetEnhMetaFileBits(hdata, size, pdata);
2401                 *lpcbytes = size;
2402
2403                 GlobalUnlock(h);
2404             }
2405         }
2406     }
2407     else
2408     {
2409         if (wformat == CF_METAFILEPICT)
2410         {
2411             h = GlobalAlloc(0, sizeof(METAFILEPICT));
2412             if (h)
2413             {
2414                 unsigned int wiresize, size;
2415                 LPMETAFILEPICT lpmfp = GlobalLock(h);
2416
2417                 memcpy(lpmfp, hdata, sizeof(METAFILEPICT));
2418                 wiresize = *lpcbytes - sizeof(METAFILEPICT);
2419                 lpmfp->hMF = SetMetaFileBitsEx(wiresize,
2420                     ((const BYTE *)hdata) + sizeof(METAFILEPICT));
2421                 size = GetMetaFileBitsEx(lpmfp->hMF, 0, NULL);
2422                 GlobalUnlock(h);
2423             }
2424         }
2425         else if (wformat == CF_ENHMETAFILE)
2426         {
2427             h = SetEnhMetaFileBits(*lpcbytes, hdata);
2428         }
2429     }
2430
2431     return h;
2432 }
2433
2434
2435 /**************************************************************************
2436  *              X11DRV_CLIPBOARD_ReleaseSelection
2437  *
2438  * Release XA_CLIPBOARD and XA_PRIMARY in response to a SelectionClear event.
2439  */
2440 static void X11DRV_CLIPBOARD_ReleaseSelection(Display *display, Atom selType, Window w, HWND hwnd, Time time)
2441 {
2442     /* w is the window that lost the selection
2443      */
2444     TRACE("event->window = %08x (selectionWindow = %08x) selectionAcquired=0x%08x\n",
2445           (unsigned)w, (unsigned)selectionWindow, (unsigned)selectionAcquired);
2446
2447     if (selectionAcquired && (w == selectionWindow))
2448     {
2449         CLIPBOARDINFO cbinfo;
2450
2451         /* completely give up the selection */
2452         TRACE("Lost CLIPBOARD (+PRIMARY) selection\n");
2453
2454         X11DRV_CLIPBOARD_GetClipboardInfo(&cbinfo);
2455
2456         if (cbinfo.flags & CB_PROCESS)
2457         {
2458             /* Since we're still the owner, this wasn't initiated by
2459                another Wine process */
2460             if (OpenClipboard(hwnd))
2461             {
2462                 /* Destroy private objects */
2463                 SendMessageW(cbinfo.hWndOwner, WM_DESTROYCLIPBOARD, 0, 0);
2464
2465                 /* Give up ownership of the windows clipboard */
2466                 X11DRV_CLIPBOARD_ReleaseOwnership();
2467                 CloseClipboard();
2468             }
2469         }
2470
2471         if ((selType == x11drv_atom(CLIPBOARD)) && (selectionAcquired & S_PRIMARY))
2472         {
2473             TRACE("Lost clipboard. Check if we need to release PRIMARY\n");
2474
2475             wine_tsx11_lock();
2476             if (selectionWindow == XGetSelectionOwner(display, XA_PRIMARY))
2477             {
2478                 TRACE("We still own PRIMARY. Releasing PRIMARY.\n");
2479                 XSetSelectionOwner(display, XA_PRIMARY, None, time);
2480             }
2481             else
2482                 TRACE("We no longer own PRIMARY\n");
2483             wine_tsx11_unlock();
2484         }
2485         else if ((selType == XA_PRIMARY) && (selectionAcquired & S_CLIPBOARD))
2486         {
2487             TRACE("Lost PRIMARY. Check if we need to release CLIPBOARD\n");
2488
2489             wine_tsx11_lock();
2490             if (selectionWindow == XGetSelectionOwner(display,x11drv_atom(CLIPBOARD)))
2491             {
2492                 TRACE("We still own CLIPBOARD. Releasing CLIPBOARD.\n");
2493                 XSetSelectionOwner(display, x11drv_atom(CLIPBOARD), None, time);
2494             }
2495             else
2496                 TRACE("We no longer own CLIPBOARD\n");
2497             wine_tsx11_unlock();
2498         }
2499
2500         selectionWindow = None;
2501
2502         X11DRV_EmptyClipboard(FALSE);
2503
2504         /* Reset the selection flags now that we are done */
2505         selectionAcquired = S_NOSELECTION;
2506     }
2507 }
2508
2509
2510 /**************************************************************************
2511  *              IsSelectionOwner (X11DRV.@)
2512  *
2513  * Returns: TRUE if the selection is owned by this process, FALSE otherwise
2514  */
2515 static BOOL X11DRV_CLIPBOARD_IsSelectionOwner(void)
2516 {
2517     return selectionAcquired;
2518 }
2519
2520
2521 /**************************************************************************
2522  *                X11DRV Clipboard Exports
2523  **************************************************************************/
2524
2525
2526 /**************************************************************************
2527  *              RegisterClipboardFormat (X11DRV.@)
2528  *
2529  * Registers a custom X clipboard format
2530  * Returns: Format id or 0 on failure
2531  */
2532 UINT CDECL X11DRV_RegisterClipboardFormat(LPCWSTR FormatName)
2533 {
2534     LPWINE_CLIPFORMAT lpFormat;
2535
2536     if (FormatName == NULL) return 0;
2537     if (!(lpFormat = register_format( FormatName, 0 ))) return 0;
2538     return lpFormat->wFormatID;
2539 }
2540
2541
2542 /**************************************************************************
2543  *              X11DRV_GetClipboardFormatName
2544  */
2545 INT CDECL X11DRV_GetClipboardFormatName(UINT wFormat, LPWSTR retStr, INT maxlen)
2546 {
2547     LPWINE_CLIPFORMAT lpFormat;
2548
2549     TRACE("(%04X, %p, %d) !\n", wFormat, retStr, maxlen);
2550
2551     if (wFormat < 0xc000)
2552     {
2553         SetLastError(ERROR_INVALID_PARAMETER);
2554         return 0;
2555     }
2556
2557     lpFormat = X11DRV_CLIPBOARD_LookupFormat(wFormat);
2558
2559     if (!lpFormat || (lpFormat->wFlags & CF_FLAG_BUILTINFMT))
2560     {
2561         TRACE("Unknown format 0x%08x!\n", wFormat);
2562         SetLastError(ERROR_INVALID_HANDLE);
2563         return 0;
2564     }
2565
2566     lstrcpynW(retStr, lpFormat->Name, maxlen);
2567
2568     return strlenW(retStr);
2569 }
2570
2571 static void selection_acquire(void)
2572 {
2573     Window owner;
2574     Display *display;
2575
2576     owner = thread_selection_wnd();
2577     display = thread_display();
2578
2579     wine_tsx11_lock();
2580
2581     selectionAcquired = 0;
2582     selectionWindow = 0;
2583
2584     /* Grab PRIMARY selection if not owned */
2585     if (use_primary_selection)
2586         XSetSelectionOwner(display, XA_PRIMARY, owner, CurrentTime);
2587
2588     /* Grab CLIPBOARD selection if not owned */
2589     XSetSelectionOwner(display, x11drv_atom(CLIPBOARD), owner, CurrentTime);
2590
2591     if (use_primary_selection && XGetSelectionOwner(display, XA_PRIMARY) == owner)
2592         selectionAcquired |= S_PRIMARY;
2593
2594     if (XGetSelectionOwner(display,x11drv_atom(CLIPBOARD)) == owner)
2595         selectionAcquired |= S_CLIPBOARD;
2596
2597     wine_tsx11_unlock();
2598
2599     if (selectionAcquired)
2600     {
2601         selectionWindow = owner;
2602         TRACE("Grabbed X selection, owner=(%08x)\n", (unsigned) owner);
2603     }
2604 }
2605
2606 static DWORD WINAPI selection_thread_proc(LPVOID p)
2607 {
2608     HANDLE event = p;
2609
2610     TRACE("\n");
2611
2612     selection_acquire();
2613     SetEvent(event);
2614
2615     while (selectionAcquired)
2616     {
2617         MsgWaitForMultipleObjectsEx(0, NULL, INFINITE, QS_SENDMESSAGE, 0);
2618     }
2619
2620     return 0;
2621 }
2622
2623 /**************************************************************************
2624  *              AcquireClipboard (X11DRV.@)
2625  */
2626 int CDECL X11DRV_AcquireClipboard(HWND hWndClipWindow)
2627 {
2628     DWORD procid;
2629     HANDLE selectionThread;
2630
2631     TRACE(" %p\n", hWndClipWindow);
2632
2633     /*
2634      * It's important that the selection get acquired from the thread
2635      * that owns the clipboard window. The primary reason is that we know 
2636      * it is running a message loop and therefore can process the 
2637      * X selection events.
2638      */
2639     if (hWndClipWindow &&
2640         GetCurrentThreadId() != GetWindowThreadProcessId(hWndClipWindow, &procid))
2641     {
2642         if (procid != GetCurrentProcessId())
2643         {
2644             WARN("Setting clipboard owner to other process is not supported\n");
2645             hWndClipWindow = NULL;
2646         }
2647         else
2648         {
2649             TRACE("Thread %x is acquiring selection with thread %x's window %p\n",
2650                 GetCurrentThreadId(),
2651                 GetWindowThreadProcessId(hWndClipWindow, NULL), hWndClipWindow);
2652
2653             return SendMessageW(hWndClipWindow, WM_X11DRV_ACQUIRE_SELECTION, 0, 0);
2654         }
2655     }
2656
2657     if (hWndClipWindow)
2658     {
2659         selection_acquire();
2660     }
2661     else
2662     {
2663         HANDLE event = CreateEventW(NULL, FALSE, FALSE, NULL);
2664         selectionThread = CreateThread(NULL, 0, &selection_thread_proc, event, 0, NULL);
2665
2666         if (!selectionThread)
2667         {
2668             WARN("Could not start clipboard thread\n");
2669             return 0;
2670         }
2671
2672         WaitForSingleObject(event, INFINITE);
2673         CloseHandle(event);
2674         CloseHandle(selectionThread);
2675     }
2676
2677     return 1;
2678 }
2679
2680
2681 /**************************************************************************
2682  *      X11DRV_EmptyClipboard
2683  *
2684  * Empty cached clipboard data. 
2685  */
2686 void CDECL X11DRV_EmptyClipboard(BOOL keepunowned)
2687 {
2688     if (ClipData)
2689     {
2690         LPWINE_CLIPDATA lpData, lpStart;
2691         LPWINE_CLIPDATA lpNext = ClipData;
2692
2693         TRACE(" called with %d entries in cache.\n", ClipDataCount);
2694
2695         do
2696         {
2697             lpStart = ClipData;
2698             lpData = lpNext;
2699             lpNext = lpData->NextData;
2700
2701             if (!keepunowned || !(lpData->wFlags & CF_FLAG_UNOWNED))
2702             {
2703             lpData->PrevData->NextData = lpData->NextData;
2704             lpData->NextData->PrevData = lpData->PrevData;
2705
2706                 if (lpData == ClipData)
2707                     ClipData = lpNext != lpData ? lpNext : NULL;
2708
2709             X11DRV_CLIPBOARD_FreeData(lpData);
2710             HeapFree(GetProcessHeap(), 0, lpData);
2711
2712                 ClipDataCount--;
2713             }
2714         } while (lpNext != lpStart);
2715     }
2716
2717     TRACE(" %d entries remaining in cache.\n", ClipDataCount);
2718 }
2719
2720
2721
2722 /**************************************************************************
2723  *              X11DRV_SetClipboardData
2724  */
2725 BOOL CDECL X11DRV_SetClipboardData(UINT wFormat, HANDLE hData, BOOL owner)
2726 {
2727     DWORD flags = 0;
2728     BOOL bResult = TRUE;
2729
2730     /* If it's not owned, data can only be set if the format data is not already owned
2731        and its rendering is not delayed */
2732     if (!owner)
2733     {
2734         CLIPBOARDINFO cbinfo;
2735         LPWINE_CLIPDATA lpRender;
2736
2737         X11DRV_CLIPBOARD_UpdateCache(&cbinfo);
2738
2739         if (!hData ||
2740             ((lpRender = X11DRV_CLIPBOARD_LookupData(wFormat)) &&
2741             !(lpRender->wFlags & CF_FLAG_UNOWNED)))
2742             bResult = FALSE;
2743         else
2744             flags = CF_FLAG_UNOWNED;
2745     }
2746
2747     bResult &= X11DRV_CLIPBOARD_InsertClipboardData(wFormat, hData, flags, NULL, TRUE);
2748
2749     return bResult;
2750 }
2751
2752
2753 /**************************************************************************
2754  *              CountClipboardFormats
2755  */
2756 INT CDECL X11DRV_CountClipboardFormats(void)
2757 {
2758     CLIPBOARDINFO cbinfo;
2759
2760     X11DRV_CLIPBOARD_UpdateCache(&cbinfo);
2761
2762     TRACE(" count=%d\n", ClipDataCount);
2763
2764     return ClipDataCount;
2765 }
2766
2767
2768 /**************************************************************************
2769  *              X11DRV_EnumClipboardFormats
2770  */
2771 UINT CDECL X11DRV_EnumClipboardFormats(UINT wFormat)
2772 {
2773     CLIPBOARDINFO cbinfo;
2774     UINT wNextFormat = 0;
2775
2776     TRACE("(%04X)\n", wFormat);
2777
2778     X11DRV_CLIPBOARD_UpdateCache(&cbinfo);
2779
2780     if (!wFormat)
2781     {
2782         if (ClipData)
2783             wNextFormat = ClipData->wFormatID;
2784     }
2785     else
2786     {
2787         LPWINE_CLIPDATA lpData = X11DRV_CLIPBOARD_LookupData(wFormat);
2788
2789         if (lpData && lpData->NextData != ClipData)
2790             wNextFormat = lpData->NextData->wFormatID;
2791     }
2792
2793     return wNextFormat;
2794 }
2795
2796
2797 /**************************************************************************
2798  *              X11DRV_IsClipboardFormatAvailable
2799  */
2800 BOOL CDECL X11DRV_IsClipboardFormatAvailable(UINT wFormat)
2801 {
2802     BOOL bRet = FALSE;
2803     CLIPBOARDINFO cbinfo;
2804
2805     TRACE("(%04X)\n", wFormat);
2806
2807     X11DRV_CLIPBOARD_UpdateCache(&cbinfo);
2808
2809     if (wFormat != 0 && X11DRV_CLIPBOARD_LookupData(wFormat))
2810         bRet = TRUE;
2811
2812     TRACE("(%04X)- ret(%d)\n", wFormat, bRet);
2813
2814     return bRet;
2815 }
2816
2817
2818 /**************************************************************************
2819  *              GetClipboardData (USER.142)
2820  */
2821 HANDLE CDECL X11DRV_GetClipboardData(UINT wFormat)
2822 {
2823     CLIPBOARDINFO cbinfo;
2824     LPWINE_CLIPDATA lpRender;
2825
2826     TRACE("(%04X)\n", wFormat);
2827
2828     X11DRV_CLIPBOARD_UpdateCache(&cbinfo);
2829
2830     if ((lpRender = X11DRV_CLIPBOARD_LookupData(wFormat)))
2831     {
2832         if ( !lpRender->hData )
2833             X11DRV_CLIPBOARD_RenderFormat(thread_init_display(), lpRender);
2834
2835         TRACE(" returning %p (type %04x)\n", lpRender->hData, lpRender->wFormatID);
2836         return lpRender->hData;
2837     }
2838
2839     return 0;
2840 }
2841
2842
2843 /**************************************************************************
2844  *              ResetSelectionOwner
2845  *
2846  * Called when the thread owning the selection is destroyed and we need to
2847  * preserve the selection ownership. We look for another top level window
2848  * in this process and send it a message to acquire the selection.
2849  */
2850 void X11DRV_ResetSelectionOwner(void)
2851 {
2852     HWND hwnd;
2853     DWORD procid;
2854
2855     TRACE("\n");
2856
2857     if (!selectionAcquired  || thread_selection_wnd() != selectionWindow)
2858         return;
2859
2860     selectionAcquired = S_NOSELECTION;
2861     selectionWindow = 0;
2862
2863     hwnd = GetWindow(GetDesktopWindow(), GW_CHILD);
2864     do
2865     {
2866         if (GetCurrentThreadId() != GetWindowThreadProcessId(hwnd, &procid))
2867         {
2868             if (GetCurrentProcessId() == procid)
2869             {
2870                 if (SendMessageW(hwnd, WM_X11DRV_ACQUIRE_SELECTION, 0, 0))
2871                     return;
2872             }
2873         }
2874     } while ((hwnd = GetWindow(hwnd, GW_HWNDNEXT)) != NULL);
2875
2876     WARN("Failed to find another thread to take selection ownership. Clipboard data will be lost.\n");
2877
2878     X11DRV_CLIPBOARD_ReleaseOwnership();
2879     X11DRV_EmptyClipboard(FALSE);
2880 }
2881
2882
2883 /**************************************************************************
2884  *                      X11DRV_CLIPBOARD_SynthesizeData
2885  */
2886 static BOOL X11DRV_CLIPBOARD_SynthesizeData(UINT wFormatID)
2887 {
2888     BOOL bsyn = TRUE;
2889     LPWINE_CLIPDATA lpSource = NULL;
2890
2891     TRACE(" %04x\n", wFormatID);
2892
2893     /* Don't need to synthesize if it already exists */
2894     if (X11DRV_CLIPBOARD_LookupData(wFormatID))
2895         return TRUE;
2896
2897     if (wFormatID == CF_UNICODETEXT || wFormatID == CF_TEXT || wFormatID == CF_OEMTEXT)
2898     {
2899         bsyn = ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_UNICODETEXT)) &&
2900             ~lpSource->wFlags & CF_FLAG_SYNTHESIZED) ||
2901             ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_TEXT)) &&
2902             ~lpSource->wFlags & CF_FLAG_SYNTHESIZED) ||
2903             ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_OEMTEXT)) &&
2904             ~lpSource->wFlags & CF_FLAG_SYNTHESIZED);
2905     }
2906     else if (wFormatID == CF_ENHMETAFILE)
2907     {
2908         bsyn = (lpSource = X11DRV_CLIPBOARD_LookupData(CF_METAFILEPICT)) &&
2909             ~lpSource->wFlags & CF_FLAG_SYNTHESIZED;
2910     }
2911     else if (wFormatID == CF_METAFILEPICT)
2912     {
2913         bsyn = (lpSource = X11DRV_CLIPBOARD_LookupData(CF_ENHMETAFILE)) &&
2914             ~lpSource->wFlags & CF_FLAG_SYNTHESIZED;
2915     }
2916     else if (wFormatID == CF_DIB)
2917     {
2918         bsyn = (lpSource = X11DRV_CLIPBOARD_LookupData(CF_BITMAP)) &&
2919             ~lpSource->wFlags & CF_FLAG_SYNTHESIZED;
2920     }
2921     else if (wFormatID == CF_BITMAP)
2922     {
2923         bsyn = (lpSource = X11DRV_CLIPBOARD_LookupData(CF_DIB)) &&
2924             ~lpSource->wFlags & CF_FLAG_SYNTHESIZED;
2925     }
2926
2927     if (bsyn)
2928         X11DRV_CLIPBOARD_InsertClipboardData(wFormatID, 0, CF_FLAG_SYNTHESIZED, NULL, TRUE);
2929
2930     return bsyn;
2931 }
2932
2933
2934
2935 /**************************************************************************
2936  *              X11DRV_EndClipboardUpdate
2937  * TODO:
2938  *  Add locale if it hasn't already been added
2939  */
2940 void CDECL X11DRV_EndClipboardUpdate(void)
2941 {
2942     INT count = ClipDataCount;
2943
2944     /* Do Unicode <-> Text <-> OEM mapping */
2945     X11DRV_CLIPBOARD_SynthesizeData(CF_TEXT);
2946     X11DRV_CLIPBOARD_SynthesizeData(CF_OEMTEXT);
2947     X11DRV_CLIPBOARD_SynthesizeData(CF_UNICODETEXT);
2948
2949     /* Enhmetafile <-> MetafilePict mapping */
2950     X11DRV_CLIPBOARD_SynthesizeData(CF_ENHMETAFILE);
2951     X11DRV_CLIPBOARD_SynthesizeData(CF_METAFILEPICT);
2952
2953     /* DIB <-> Bitmap mapping */
2954     X11DRV_CLIPBOARD_SynthesizeData(CF_DIB);
2955     X11DRV_CLIPBOARD_SynthesizeData(CF_BITMAP);
2956
2957     TRACE("%d formats added to cached data\n", ClipDataCount - count);
2958 }
2959
2960
2961 /***********************************************************************
2962  *           X11DRV_SelectionRequest_TARGETS
2963  *  Service a TARGETS selection request event
2964  */
2965 static Atom X11DRV_SelectionRequest_TARGETS( Display *display, Window requestor,
2966                                              Atom target, Atom rprop )
2967 {
2968     UINT i;
2969     Atom* targets;
2970     ULONG cTargets;
2971     LPWINE_CLIPFORMAT lpFormats;
2972     LPWINE_CLIPDATA lpData;
2973
2974     /* Create X atoms for any clipboard types which don't have atoms yet.
2975      * This avoids sending bogus zero atoms.
2976      * Without this, copying might not have access to all clipboard types.
2977      * FIXME: is it safe to call this here?
2978      */
2979     intern_atoms();
2980
2981     /*
2982      * Count the number of items we wish to expose as selection targets.
2983      */
2984     cTargets = 1; /* Include TARGETS */
2985
2986     if (!(lpData = ClipData)) return None;
2987
2988     do
2989     {
2990         lpFormats = ClipFormats;
2991
2992         while (lpFormats)
2993         {
2994             if ((lpFormats->wFormatID == lpData->wFormatID) &&
2995                 lpFormats->lpDrvExportFunc && lpFormats->drvData)
2996                 cTargets++;
2997
2998             lpFormats = lpFormats->NextFormat;
2999         }
3000
3001         lpData = lpData->NextData;
3002     }
3003     while (lpData != ClipData);
3004
3005     TRACE(" found %d formats\n", cTargets);
3006
3007     /* Allocate temp buffer */
3008     targets = HeapAlloc( GetProcessHeap(), 0, cTargets * sizeof(Atom));
3009     if(targets == NULL)
3010         return None;
3011
3012     i = 0;
3013     lpData = ClipData;
3014     targets[i++] = x11drv_atom(TARGETS);
3015
3016     do
3017     {
3018         lpFormats = ClipFormats;
3019
3020         while (lpFormats)
3021         {
3022             if ((lpFormats->wFormatID == lpData->wFormatID) &&
3023                 lpFormats->lpDrvExportFunc && lpFormats->drvData)
3024                 targets[i++] = lpFormats->drvData;
3025
3026             lpFormats = lpFormats->NextFormat;
3027         }
3028
3029         lpData = lpData->NextData;
3030     }
3031     while (lpData != ClipData);
3032
3033     wine_tsx11_lock();
3034
3035     if (TRACE_ON(clipboard))
3036     {
3037         unsigned int i;
3038         for ( i = 0; i < cTargets; i++)
3039         {
3040             char *itemFmtName = XGetAtomName(display, targets[i]);
3041             TRACE("\tAtom# %d:  Property %ld Type %s\n", i, targets[i], itemFmtName);
3042             XFree(itemFmtName);
3043         }
3044     }
3045
3046     /* We may want to consider setting the type to xaTargets instead,
3047      * in case some apps expect this instead of XA_ATOM */
3048     XChangeProperty(display, requestor, rprop, XA_ATOM, 32,
3049                     PropModeReplace, (unsigned char *)targets, cTargets);
3050     wine_tsx11_unlock();
3051
3052     HeapFree(GetProcessHeap(), 0, targets);
3053
3054     return rprop;
3055 }
3056
3057
3058 /***********************************************************************
3059  *           X11DRV_SelectionRequest_MULTIPLE
3060  *  Service a MULTIPLE selection request event
3061  *  rprop contains a list of (target,property) atom pairs.
3062  *  The first atom names a target and the second names a property.
3063  *  The effect is as if we have received a sequence of SelectionRequest events
3064  *  (one for each atom pair) except that:
3065  *  1. We reply with a SelectionNotify only when all the requested conversions
3066  *  have been performed.
3067  *  2. If we fail to convert the target named by an atom in the MULTIPLE property,
3068  *  we replace the atom in the property by None.
3069  */
3070 static Atom X11DRV_SelectionRequest_MULTIPLE( HWND hWnd, XSelectionRequestEvent *pevent )
3071 {
3072     Display *display = pevent->display;
3073     Atom           rprop;
3074     Atom           atype=AnyPropertyType;
3075     int            aformat;
3076     unsigned long  remain;
3077     Atom*          targetPropList=NULL;
3078     unsigned long  cTargetPropList = 0;
3079
3080     /* If the specified property is None the requestor is an obsolete client.
3081      * We support these by using the specified target atom as the reply property.
3082      */
3083     rprop = pevent->property;
3084     if( rprop == None )
3085         rprop = pevent->target;
3086     if (!rprop)
3087         return 0;
3088
3089     /* Read the MULTIPLE property contents. This should contain a list of
3090      * (target,property) atom pairs.
3091      */
3092     wine_tsx11_lock();
3093     if(XGetWindowProperty(display, pevent->requestor, rprop,
3094                           0, 0x3FFF, False, AnyPropertyType, &atype,&aformat,
3095                           &cTargetPropList, &remain,
3096                           (unsigned char**)&targetPropList) != Success)
3097     {
3098         wine_tsx11_unlock();
3099         TRACE("\tCouldn't read MULTIPLE property\n");
3100     }
3101     else
3102     {
3103         TRACE("\tType %s,Format %d,nItems %ld, Remain %ld\n",
3104               XGetAtomName(display, atype), aformat, cTargetPropList, remain);
3105         wine_tsx11_unlock();
3106
3107         /*
3108          * Make sure we got what we expect.
3109          * NOTE: According to the X-ICCCM Version 2.0 documentation the property sent
3110          * in a MULTIPLE selection request should be of type ATOM_PAIR.
3111          * However some X apps(such as XPaint) are not compliant with this and return
3112          * a user defined atom in atype when XGetWindowProperty is called.
3113          * The data *is* an atom pair but is not denoted as such.
3114          */
3115         if(aformat == 32 /* atype == xAtomPair */ )
3116         {
3117             unsigned int i;
3118
3119             /* Iterate through the ATOM_PAIR list and execute a SelectionRequest
3120              * for each (target,property) pair */
3121
3122             for (i = 0; i < cTargetPropList; i+=2)
3123             {
3124                 XSelectionRequestEvent event;
3125
3126                 if (TRACE_ON(clipboard))
3127                 {
3128                     char *targetName, *propName;
3129                     wine_tsx11_lock();
3130                     targetName = XGetAtomName(display, targetPropList[i]);
3131                     propName = XGetAtomName(display, targetPropList[i+1]);
3132                     TRACE("MULTIPLE(%d): Target='%s' Prop='%s'\n",
3133                           i/2, targetName, propName);
3134                     XFree(targetName);
3135                     XFree(propName);
3136                     wine_tsx11_unlock();
3137                 }
3138
3139                 /* We must have a non "None" property to service a MULTIPLE target atom */
3140                 if ( !targetPropList[i+1] )
3141                 {
3142                     TRACE("\tMULTIPLE(%d): Skipping target with empty property!\n", i);
3143                     continue;
3144                 }
3145
3146                 /* Set up an XSelectionRequestEvent for this (target,property) pair */
3147                 event = *pevent;
3148                 event.target = targetPropList[i];
3149                 event.property = targetPropList[i+1];
3150
3151                 /* Fire a SelectionRequest, informing the handler that we are processing
3152                  * a MULTIPLE selection request event.
3153                  */
3154                 X11DRV_HandleSelectionRequest( hWnd, &event, TRUE );
3155             }
3156         }
3157
3158         /* Free the list of targets/properties */
3159         wine_tsx11_lock();
3160         XFree(targetPropList);
3161         wine_tsx11_unlock();
3162     }
3163
3164     return rprop;
3165 }
3166
3167
3168 /***********************************************************************
3169  *           X11DRV_HandleSelectionRequest
3170  *  Process an event selection request event.
3171  *  The bIsMultiple flag is used to signal when EVENT_SelectionRequest is called
3172  *  recursively while servicing a "MULTIPLE" selection target.
3173  *
3174  *  Note: We only receive this event when WINE owns the X selection
3175  */
3176 static void X11DRV_HandleSelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple )
3177 {
3178     Display *display = event->display;
3179     XSelectionEvent result;
3180     Atom rprop = None;
3181     Window request = event->requestor;
3182
3183     TRACE("\n");
3184
3185     /*
3186      * We can only handle the selection request if :
3187      * The selection is PRIMARY or CLIPBOARD, AND we can successfully open the clipboard.
3188      * Don't do these checks or open the clipboard while recursively processing MULTIPLE,
3189      * since this has been already done.
3190      */
3191     if ( !bIsMultiple )
3192     {
3193         if (((event->selection != XA_PRIMARY) && (event->selection != x11drv_atom(CLIPBOARD))))
3194             goto END;
3195     }
3196
3197     /* If the specified property is None the requestor is an obsolete client.
3198      * We support these by using the specified target atom as the reply property.
3199      */
3200     rprop = event->property;
3201     if( rprop == None )
3202         rprop = event->target;
3203
3204     if(event->target == x11drv_atom(TARGETS))  /*  Return a list of all supported targets */
3205     {
3206         /* TARGETS selection request */
3207         rprop = X11DRV_SelectionRequest_TARGETS( display, request, event->target, rprop );
3208     }
3209     else if(event->target == x11drv_atom(MULTIPLE))  /*  rprop contains a list of (target, property) atom pairs */
3210     {
3211         /* MULTIPLE selection request */
3212         rprop = X11DRV_SelectionRequest_MULTIPLE( hWnd, event );
3213     }
3214     else
3215     {
3216         LPWINE_CLIPFORMAT lpFormat = X11DRV_CLIPBOARD_LookupProperty(NULL, event->target);
3217
3218         if (lpFormat && lpFormat->lpDrvExportFunc)
3219         {
3220             LPWINE_CLIPDATA lpData = X11DRV_CLIPBOARD_LookupData(lpFormat->wFormatID);
3221
3222             if (lpData)
3223             {
3224                 unsigned char* lpClipData;
3225                 DWORD cBytes;
3226                 HANDLE hClipData = lpFormat->lpDrvExportFunc(display, request, event->target,
3227                                                              rprop, lpData, &cBytes);
3228
3229                 if (hClipData && (lpClipData = GlobalLock(hClipData)))
3230                 {
3231                     TRACE("\tUpdating property %s, %d bytes\n", debugstr_w(lpFormat->Name), cBytes);
3232
3233                     wine_tsx11_lock();
3234                     XChangeProperty(display, request, rprop, event->target,
3235                                     8, PropModeReplace, lpClipData, cBytes);
3236                     wine_tsx11_unlock();
3237
3238                     GlobalUnlock(hClipData);
3239                     GlobalFree(hClipData);
3240                 }
3241             }
3242         }
3243     }
3244
3245 END:
3246     /* reply to sender
3247      * SelectionNotify should be sent only at the end of a MULTIPLE request
3248      */
3249     if ( !bIsMultiple )
3250     {
3251         result.type = SelectionNotify;
3252         result.display = display;
3253         result.requestor = request;
3254         result.selection = event->selection;
3255         result.property = rprop;
3256         result.target = event->target;
3257         result.time = event->time;
3258         TRACE("Sending SelectionNotify event...\n");
3259         wine_tsx11_lock();
3260         XSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
3261         wine_tsx11_unlock();
3262     }
3263 }
3264
3265
3266 /***********************************************************************
3267  *           X11DRV_SelectionRequest
3268  */
3269 void X11DRV_SelectionRequest( HWND hWnd, XEvent *event )
3270 {
3271     X11DRV_HandleSelectionRequest( hWnd, &event->xselectionrequest, FALSE );
3272 }
3273
3274
3275 /***********************************************************************
3276  *           X11DRV_SelectionClear
3277  */
3278 void X11DRV_SelectionClear( HWND hWnd, XEvent *xev )
3279 {
3280     XSelectionClearEvent *event = &xev->xselectionclear;
3281     if (event->selection == XA_PRIMARY || event->selection == x11drv_atom(CLIPBOARD))
3282         X11DRV_CLIPBOARD_ReleaseSelection( event->display, event->selection,
3283                                            event->window, hWnd, event->time );
3284 }
3285
3286 /***********************************************************************
3287  *           X11DRV_Clipboard_Cleanup
3288  */
3289 void X11DRV_Clipboard_Cleanup(void)
3290 {
3291     selectionAcquired = S_NOSELECTION;
3292
3293     X11DRV_EmptyClipboard(FALSE);
3294 }