Stub implementations for AbortPrinter, AddPortEx{A,W},
[wine] / dlls / x11drv / 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 <time.h>
76
77 #include "windef.h"
78 #include "winbase.h"
79 #include "winreg.h"
80 #include "wine/wingdi16.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 #define HGDIOBJ_32(handle16)  ((HGDIOBJ)(ULONG_PTR)(handle16))
89
90 /* Maximum wait time for selection notify */
91 #define SELECTION_RETRIES 500  /* wait for .1 seconds */
92 #define SELECTION_WAIT    1000 /* us */
93 /* Minimum seconds that must lapse between owner queries */
94 #define OWNERQUERYLAPSETIME 1
95
96 /* Selection masks */
97 #define S_NOSELECTION    0
98 #define S_PRIMARY        1
99 #define S_CLIPBOARD      2
100
101 typedef struct
102 {
103     HWND hWndOpen;
104     HWND hWndOwner;
105     HWND hWndViewer;
106     UINT seqno;
107     UINT flags;
108 } CLIPBOARDINFO, *LPCLIPBOARDINFO;
109
110 static int selectionAcquired = 0;              /* Contains the current selection masks */
111 static Window selectionWindow = None;          /* The top level X window which owns the selection */
112 static BOOL usePrimary = FALSE;                /* Use primary selection in additon to the clipboard selection */
113 static Atom selectionCacheSrc = XA_PRIMARY;    /* The selection source from which the clipboard cache was filled */
114
115 INT X11DRV_RegisterClipboardFormat(LPCWSTR FormatName);
116 void X11DRV_EmptyClipboard(BOOL keepunowned);
117 void X11DRV_EndClipboardUpdate(void);
118 HANDLE X11DRV_CLIPBOARD_ImportClipboardData(LPBYTE lpdata, UINT cBytes);
119 HANDLE X11DRV_CLIPBOARD_ImportEnhMetaFile(LPBYTE lpdata, UINT cBytes);
120 HANDLE X11DRV_CLIPBOARD_ImportMetaFilePict(LPBYTE lpdata, UINT cBytes);
121 HANDLE X11DRV_CLIPBOARD_ImportXAPIXMAP(LPBYTE lpdata, UINT cBytes);
122 HANDLE X11DRV_CLIPBOARD_ImportXAString(LPBYTE lpdata, UINT cBytes);
123 HANDLE X11DRV_CLIPBOARD_ExportClipboardData(Window requestor, Atom aTarget,
124     Atom rprop, LPWINE_CLIPDATA lpData, LPDWORD lpBytes);
125 HANDLE X11DRV_CLIPBOARD_ExportString(Window requestor, Atom aTarget,
126     Atom rprop, LPWINE_CLIPDATA lpData, LPDWORD lpBytes);
127 HANDLE X11DRV_CLIPBOARD_ExportXAPIXMAP(Window requestor, Atom aTarget,
128     Atom rprop, LPWINE_CLIPDATA lpdata, LPDWORD lpBytes);
129 HANDLE X11DRV_CLIPBOARD_ExportMetaFilePict(Window requestor, Atom aTarget,
130     Atom rprop, LPWINE_CLIPDATA lpdata, LPDWORD lpBytes);
131 HANDLE X11DRV_CLIPBOARD_ExportEnhMetaFile(Window requestor, Atom aTarget,
132     Atom rprop, LPWINE_CLIPDATA lpdata, LPDWORD lpBytes);
133 static WINE_CLIPFORMAT *X11DRV_CLIPBOARD_InsertClipboardFormat(LPCWSTR FormatName, Atom prop);
134 static BOOL X11DRV_CLIPBOARD_ReadSelection(LPWINE_CLIPFORMAT lpData, Window w, Atom prop);
135 static BOOL X11DRV_CLIPBOARD_RenderSynthesizedText(UINT wFormatID);
136 static void X11DRV_CLIPBOARD_FreeData(LPWINE_CLIPDATA lpData);
137 static BOOL X11DRV_CLIPBOARD_IsSelectionOwner(void);
138 static int X11DRV_CLIPBOARD_QueryAvailableData(LPCLIPBOARDINFO lpcbinfo);
139 static BOOL X11DRV_CLIPBOARD_ReadClipboardData(UINT wFormat);
140 static BOOL X11DRV_CLIPBOARD_RenderFormat(LPWINE_CLIPDATA lpData);
141 static HANDLE X11DRV_CLIPBOARD_SerializeMetafile(INT wformat, HANDLE hdata, LPDWORD lpcbytes, BOOL out);
142 static BOOL X11DRV_CLIPBOARD_SynthesizeData(UINT wFormatID);
143 static BOOL X11DRV_CLIPBOARD_RenderSynthesizedFormat(LPWINE_CLIPDATA lpData);
144 static BOOL X11DRV_CLIPBOARD_RenderSynthesizedDIB(void);
145 static BOOL X11DRV_CLIPBOARD_RenderSynthesizedBitmap(void);
146
147 /* Clipboard formats
148  * WARNING: This data ordering is dependent on the WINE_CLIPFORMAT structure
149  * declared in clipboard.h
150  */
151 static const WCHAR wszCF_TEXT[] = {'W','C','F','_','T','E','X','T',0};
152 static const WCHAR wszCF_BITMAP[] = {'W','C','F','_','B','I','T','M','A','P',0};
153 static const WCHAR wszCF_METAFILEPICT[] = {'W','C','F','_','M','E','T','A','F','I','L','E','P','I','C','T',0};
154 static const WCHAR wszCF_SYLK[] = {'W','C','F','_','S','Y','L','K',0};
155 static const WCHAR wszCF_DIF[] = {'W','C','F','_','D','I','F',0};
156 static const WCHAR wszCF_TIFF[] = {'W','C','F','_','T','I','F','F',0};
157 static const WCHAR wszCF_OEMTEXT[] = {'W','C','F','_','O','E','M','T','E','X','T',0};
158 static const WCHAR wszCF_DIB[] = {'W','C','F','_','D','I','B',0};
159 static const WCHAR wszCF_PALETTE[] = {'W','C','F','_','P','A','L','E','T','T','E',0};
160 static const WCHAR wszCF_PENDATA[] = {'W','C','F','_','P','E','N','D','A','T','A',0};
161 static const WCHAR wszCF_RIFF[] = {'W','C','F','_','R','I','F','F',0};
162 static const WCHAR wszCF_WAVE[] = {'W','C','F','_','W','A','V','E',0};
163 static const WCHAR wszCF_UNICODETEXT[] = {'W','C','F','_','U','N','I','C','O','D','E','T','E','X','T',0};
164 static const WCHAR wszCF_ENHMETAFILE[] = {'W','C','F','_','E','N','H','M','E','T','A','F','I','L','E',0};
165 static const WCHAR wszCF_HDROP[] = {'W','C','F','_','H','D','R','O','P',0};
166 static const WCHAR wszCF_LOCALE[] = {'W','C','F','_','L','O','C','A','L','E',0};
167 static const WCHAR wszCF_DIBV5[] = {'W','C','F','_','D','I','B','V','5',0};
168 static const WCHAR wszCF_OWNERDISPLAY[] = {'W','C','F','_','O','W','N','E','R','D','I','S','P','L','A','Y',0};
169 static const WCHAR wszCF_DSPTEXT[] = {'W','C','F','_','D','S','P','T','E','X','T',0};
170 static const WCHAR wszCF_DSPBITMAP[] = {'W','C','F','_','D','S','P','B','I','T','M','A','P',0};
171 static const WCHAR wszCF_DSPMETAFILEPICT[] = {'W','C','F','_','D','S','P','M','E','T','A','F','I','L','E','P','I','C','T',0};
172 static const WCHAR wszCF_DSPENHMETAFILE[] = {'W','C','F','_','D','S','P','E','N','H','M','E','T','A','F','I','L','E',0};
173
174 static WINE_CLIPFORMAT ClipFormats[]  =
175 {
176     { CF_TEXT, wszCF_TEXT, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
177         X11DRV_CLIPBOARD_ExportClipboardData, NULL, &ClipFormats[1]},
178
179     { CF_BITMAP, wszCF_BITMAP, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
180         NULL, &ClipFormats[0], &ClipFormats[2]},
181
182     { CF_METAFILEPICT, wszCF_METAFILEPICT, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportMetaFilePict,
183         X11DRV_CLIPBOARD_ExportMetaFilePict, &ClipFormats[1], &ClipFormats[3]},
184
185     { CF_SYLK, wszCF_SYLK, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
186         X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[2], &ClipFormats[4]},
187
188     { CF_DIF, wszCF_DIF, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
189         X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[3], &ClipFormats[5]},
190
191     { CF_TIFF, wszCF_TIFF, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
192         X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[4], &ClipFormats[6]},
193
194     { CF_OEMTEXT, wszCF_OEMTEXT, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
195         X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[5], &ClipFormats[7]},
196
197     { CF_DIB, wszCF_DIB, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportXAPIXMAP,
198         X11DRV_CLIPBOARD_ExportXAPIXMAP, &ClipFormats[6], &ClipFormats[8]},
199
200     { CF_PALETTE, wszCF_PALETTE, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
201         X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[7], &ClipFormats[9]},
202
203     { CF_PENDATA, wszCF_PENDATA, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
204         X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[8], &ClipFormats[10]},
205
206     { CF_RIFF, wszCF_RIFF, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
207         X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[9], &ClipFormats[11]},
208
209     { CF_WAVE, wszCF_WAVE, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
210         X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[10], &ClipFormats[12]},
211
212     { CF_UNICODETEXT, wszCF_UNICODETEXT, XA_STRING, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportXAString,
213         X11DRV_CLIPBOARD_ExportString, &ClipFormats[11], &ClipFormats[13]},
214
215     { CF_ENHMETAFILE, wszCF_ENHMETAFILE, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportEnhMetaFile,
216         X11DRV_CLIPBOARD_ExportEnhMetaFile, &ClipFormats[12], &ClipFormats[14]},
217
218     { CF_HDROP, wszCF_HDROP, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
219         X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[13], &ClipFormats[15]},
220
221     { CF_LOCALE, wszCF_LOCALE, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
222         X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[14], &ClipFormats[16]},
223
224     { CF_DIBV5, wszCF_DIBV5, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
225         X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[15], &ClipFormats[17]},
226
227     { CF_OWNERDISPLAY, wszCF_OWNERDISPLAY, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
228         X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[16], &ClipFormats[18]},
229
230     { CF_DSPTEXT, wszCF_DSPTEXT, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
231         X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[17], &ClipFormats[19]},
232
233     { CF_DSPBITMAP, wszCF_DSPBITMAP, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
234         X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[18], &ClipFormats[20]},
235
236     { CF_DSPMETAFILEPICT, wszCF_DSPMETAFILEPICT, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
237         X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[19], &ClipFormats[21]},
238
239     { CF_DSPENHMETAFILE, wszCF_DSPENHMETAFILE, 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
240         X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[20], NULL}
241 };
242
243 #define GET_ATOM(prop)  (((prop) < FIRST_XATOM) ? (Atom)(prop) : X11DRV_Atoms[(prop) - FIRST_XATOM])
244
245 /* Maps X properties to Windows formats */
246 static const WCHAR wszRichTextFormat[] = {'R','i','c','h',' ','T','e','x','t',' ','F','o','r','m','a','t',0};
247 static const WCHAR wszGIF[] = {'G','I','F',0};
248 static const struct
249 {
250     LPCWSTR lpszFormat;
251     UINT   prop;
252 } PropertyFormatMap[] =
253 {
254     { wszRichTextFormat, XATOM_text_rtf },
255     /* Temporarily disable text/html because Evolution incorrectly pastes strings with extra nulls */
256     /*{ "text/html", "HTML Format" },*/
257     { wszGIF, XATOM_image_gif }
258 };
259
260
261 /* Maps equivalent X properties. It is assumed that lpszProperty must already 
262    be in ClipFormats or PropertyFormatMap. */
263 static const struct
264 {
265     UINT drvDataProperty;
266     UINT drvDataAlias;
267 } PropertyAliasMap[] =
268 {
269     /* DataProperty,   DataAlias */
270     { XATOM_text_rtf,  XATOM_text_richtext },
271     { XA_STRING,       XATOM_COMPOUND_TEXT },
272     { XA_STRING,       XATOM_TEXT },
273     { XATOM_WCF_DIB,   XA_PIXMAP },
274 };
275
276
277 /*
278  * Cached clipboard data.
279  */
280 static LPWINE_CLIPDATA ClipData = NULL;
281 static UINT ClipDataCount = 0;
282
283 /*
284  * Clipboard sequence number
285  */
286 static UINT wSeqNo = 0;
287
288 #define IS_OPTION_TRUE(ch) ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
289
290 /**************************************************************************
291  *                Internal Clipboard implementation methods
292  **************************************************************************/
293
294 /**************************************************************************
295  *              X11DRV_InitClipboard
296  */
297 void X11DRV_InitClipboard(void)
298 {
299     UINT i;
300     HKEY hkey;
301
302     if(!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\Clipboard", &hkey))
303     {
304         char buffer[20];
305         DWORD type, count = sizeof(buffer);
306         if(!RegQueryValueExA(hkey, "UsePrimary", 0, &type, buffer, &count))
307             usePrimary = IS_OPTION_TRUE( buffer[0] );
308         RegCloseKey(hkey);
309     }
310
311     /* Register known mapping between window formats and X properties */
312     for (i = 0; i < sizeof(PropertyFormatMap)/sizeof(PropertyFormatMap[0]); i++)
313         X11DRV_CLIPBOARD_InsertClipboardFormat(PropertyFormatMap[i].lpszFormat,
314                                                GET_ATOM(PropertyFormatMap[i].prop));
315 }
316
317
318 /**************************************************************************
319  *                intern_atoms
320  *
321  * Intern atoms for formats that don't have one yet.
322  */
323 static void intern_atoms(void)
324 {
325     LPWINE_CLIPFORMAT format;
326     int i, count, len;
327     char **names;
328     Atom *atoms;
329
330     for (format = ClipFormats, count = 0; format; format = format->NextFormat)
331         if (!format->drvData) count++;
332     if (!count) return;
333
334     names = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*names) );
335     atoms = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*atoms) );
336
337     for (format = ClipFormats, i = 0; format; format = format->NextFormat) {
338         if (!format->drvData) {
339             len = WideCharToMultiByte(CP_UNIXCP, 0, format->Name, -1, NULL, -1, 0, 0);
340             names[i] = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
341             WideCharToMultiByte(CP_UNIXCP, 0, format->Name, -1, names[i++], len, 0, 0);
342         }
343     }
344
345     wine_tsx11_lock();
346     XInternAtoms( thread_display(), names, count, False, atoms );
347     wine_tsx11_unlock();
348
349     for (format = ClipFormats, i = 0; format; format = format->NextFormat) {
350         if (!format->drvData) {
351             HeapFree(GetProcessHeap(), 0, names[i]);
352             format->drvData = atoms[i++];
353         }
354     }
355
356     HeapFree( GetProcessHeap(), 0, names );
357     HeapFree( GetProcessHeap(), 0, atoms );
358 }
359
360
361 /**************************************************************************
362  *              register_format
363  *
364  * Register a custom X clipboard format.
365  */
366 static WINE_CLIPFORMAT *register_format( LPCWSTR FormatName, Atom prop )
367 {
368     LPWINE_CLIPFORMAT lpFormat = ClipFormats;
369
370     TRACE("%s\n", debugstr_w(FormatName));
371
372     /* walk format chain to see if it's already registered */
373     while (lpFormat)
374     {
375         if (CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, lpFormat->Name, -1, FormatName, -1) == CSTR_EQUAL
376             && (lpFormat->wFlags & CF_FLAG_BUILTINFMT) == 0)
377              return lpFormat;
378         lpFormat = lpFormat->NextFormat;
379     }
380
381     return X11DRV_CLIPBOARD_InsertClipboardFormat(FormatName, prop);
382 }
383
384
385 /**************************************************************************
386  *                X11DRV_CLIPBOARD_LookupFormat
387  */
388 LPWINE_CLIPFORMAT X11DRV_CLIPBOARD_LookupFormat(WORD wID)
389 {
390     LPWINE_CLIPFORMAT lpFormat = ClipFormats;
391
392     while(lpFormat)
393     {
394         if (lpFormat->wFormatID == wID) 
395             break;
396
397         lpFormat = lpFormat->NextFormat;
398     }
399     if (lpFormat && !lpFormat->drvData) intern_atoms();
400     return lpFormat;
401 }
402
403
404 /**************************************************************************
405  *                X11DRV_CLIPBOARD_LookupProperty
406  */
407 LPWINE_CLIPFORMAT X11DRV_CLIPBOARD_LookupProperty(UINT drvData)
408 {
409     for (;;)
410     {
411         LPWINE_CLIPFORMAT lpFormat = ClipFormats;
412         BOOL need_intern = FALSE;
413
414         while(lpFormat)
415         {
416             if (lpFormat->drvData == drvData) return lpFormat;
417             if (!lpFormat->drvData) need_intern = TRUE;
418             lpFormat = lpFormat->NextFormat;
419         }
420         if (!need_intern) return NULL;
421         intern_atoms();
422         /* restart the search for the new atoms */
423     }
424 }
425
426
427 /**************************************************************************
428  *                X11DRV_CLIPBOARD_LookupAliasProperty
429  */
430 LPWINE_CLIPFORMAT X11DRV_CLIPBOARD_LookupAliasProperty(UINT drvDataAlias)
431 {
432     unsigned int i;
433     LPWINE_CLIPFORMAT lpFormat = NULL;
434
435     for (i = 0; i < sizeof(PropertyAliasMap)/sizeof(PropertyAliasMap[0]); i++)
436     {
437         if (GET_ATOM(PropertyAliasMap[i].drvDataAlias) == drvDataAlias)
438         {
439             lpFormat = X11DRV_CLIPBOARD_LookupProperty(GET_ATOM(PropertyAliasMap[i].drvDataProperty));
440             break;
441         }
442    }
443
444     return lpFormat;
445 }
446
447
448 /**************************************************************************
449  *                X11DRV_CLIPBOARD_LookupPropertyAlias
450  */
451 UINT  X11DRV_CLIPBOARD_LookupPropertyAlias(UINT drvDataProperty)
452 {
453     unsigned int i;
454     UINT alias = 0;
455
456     for (i = 0; i < sizeof(PropertyAliasMap)/sizeof(PropertyAliasMap[0]); i++)
457     {
458         if (GET_ATOM(PropertyAliasMap[i].drvDataProperty) == drvDataProperty)
459         {
460             alias = GET_ATOM(PropertyAliasMap[i].drvDataAlias);
461             break;
462         }
463    }
464
465     return alias;
466 }
467
468
469 /**************************************************************************
470  *               X11DRV_CLIPBOARD_LookupData
471  */
472 LPWINE_CLIPDATA X11DRV_CLIPBOARD_LookupData(DWORD wID)
473 {
474     LPWINE_CLIPDATA lpData = ClipData;
475
476     if (lpData)
477     {
478         do
479         {
480             if (lpData->wFormatID == wID) 
481                 break;
482
483             lpData = lpData->NextData;
484         }
485         while(lpData != ClipData);
486
487         if (lpData->wFormatID != wID)
488             lpData = NULL;
489     }
490
491     return lpData;
492 }
493
494
495 /**************************************************************************
496  *              InsertClipboardFormat
497  */
498 static WINE_CLIPFORMAT *X11DRV_CLIPBOARD_InsertClipboardFormat(LPCWSTR FormatName, Atom prop)
499 {
500     LPWINE_CLIPFORMAT lpFormat;
501     LPWINE_CLIPFORMAT lpNewFormat;
502    
503     /* allocate storage for new format entry */
504     lpNewFormat = (LPWINE_CLIPFORMAT) HeapAlloc(GetProcessHeap(), 
505         0, sizeof(WINE_CLIPFORMAT));
506
507     if(lpNewFormat == NULL) 
508     {
509         WARN("No more memory for a new format!\n");
510         return NULL;
511     }
512
513     if (!(lpNewFormat->Name = HeapAlloc(GetProcessHeap(), 0, (strlenW(FormatName)+1)*sizeof(WCHAR))))
514     {
515         WARN("No more memory for the new format name!\n");
516         HeapFree(GetProcessHeap(), 0, lpNewFormat);
517         return NULL;
518     }
519
520     strcpyW((LPWSTR)lpNewFormat->Name, FormatName);
521     lpNewFormat->wFlags = 0;
522     lpNewFormat->wFormatID = GlobalAddAtomW(lpNewFormat->Name);
523     lpNewFormat->drvData = prop;
524     lpNewFormat->lpDrvImportFunc = X11DRV_CLIPBOARD_ImportClipboardData;
525     lpNewFormat->lpDrvExportFunc = X11DRV_CLIPBOARD_ExportClipboardData;
526
527     /* Link Format */
528     lpFormat = ClipFormats;
529
530     while(lpFormat->NextFormat) /* Move to last entry */
531         lpFormat = lpFormat->NextFormat;
532
533     lpNewFormat->NextFormat = NULL;
534     lpFormat->NextFormat = lpNewFormat;
535     lpNewFormat->PrevFormat = lpFormat;
536
537     TRACE("Registering format(%d): %s drvData %d\n",
538         lpNewFormat->wFormatID, debugstr_w(FormatName), lpNewFormat->drvData);
539
540     return lpNewFormat;
541 }
542
543
544
545
546 /**************************************************************************
547  *                      X11DRV_CLIPBOARD_GetClipboardInfo
548  */
549 static BOOL X11DRV_CLIPBOARD_GetClipboardInfo(LPCLIPBOARDINFO cbInfo)
550 {
551     BOOL bRet = FALSE;
552
553     SERVER_START_REQ( set_clipboard_info )
554     {
555         req->flags = 0;
556
557         if (wine_server_call_err( req ))
558         {
559             ERR("Failed to get clipboard owner.\n");
560         }
561         else
562         {
563             cbInfo->hWndOpen = reply->old_clipboard;
564             cbInfo->hWndOwner = reply->old_owner;
565             cbInfo->hWndViewer = reply->old_viewer;
566             cbInfo->seqno = reply->seqno;
567             cbInfo->flags = reply->flags;
568
569             bRet = TRUE;
570         }
571     }
572     SERVER_END_REQ;
573
574     return bRet;
575 }
576
577
578 /**************************************************************************
579  *      X11DRV_CLIPBOARD_ReleaseOwnership
580  */
581 static BOOL X11DRV_CLIPBOARD_ReleaseOwnership(void)
582 {
583     BOOL bRet = FALSE;
584
585     SERVER_START_REQ( set_clipboard_info )
586     {
587         req->flags = SET_CB_RELOWNER | SET_CB_SEQNO;
588
589         if (wine_server_call_err( req ))
590         {
591             ERR("Failed to set clipboard.\n");
592         }
593         else
594         {
595             bRet = TRUE;
596         }
597     }
598     SERVER_END_REQ;
599
600     return bRet;
601 }
602
603
604
605 /**************************************************************************
606  *                      X11DRV_CLIPBOARD_InsertClipboardData
607  *
608  * Caller *must* have the clipboard open and be the owner.
609  */
610 static BOOL X11DRV_CLIPBOARD_InsertClipboardData(UINT wFormat, HANDLE16 hData16, HANDLE hData32, DWORD flags)
611 {
612     LPWINE_CLIPDATA lpData = X11DRV_CLIPBOARD_LookupData(wFormat);
613
614     TRACE("format=%d lpData=%p hData16=%08x hData32=%08x flags=0x%08lx\n", 
615         wFormat, lpData, hData16, (unsigned int)hData32, flags);
616
617     if (lpData)
618     {
619         X11DRV_CLIPBOARD_FreeData(lpData);
620
621         lpData->hData16 = hData16;  /* 0 is legal, see WM_RENDERFORMAT */
622         lpData->hData32 = hData32;
623     }
624     else
625     {
626         lpData = (LPWINE_CLIPDATA) HeapAlloc(GetProcessHeap(), 
627             0, sizeof(WINE_CLIPDATA));
628
629         lpData->wFormatID = wFormat;
630         lpData->hData16 = hData16;  /* 0 is legal, see WM_RENDERFORMAT */
631         lpData->hData32 = hData32;
632         lpData->drvData = 0;
633
634         if (ClipData)
635         {
636             LPWINE_CLIPDATA lpPrevData = ClipData->PrevData;
637
638             lpData->PrevData = lpPrevData;
639             lpData->NextData = ClipData;
640
641             lpPrevData->NextData = lpData;
642             ClipData->PrevData = lpData;
643         }
644         else
645         {
646             lpData->NextData = lpData;
647             lpData->PrevData = lpData;
648             ClipData = lpData;
649         }
650
651         ClipDataCount++;
652     }
653
654     lpData->wFlags = flags;
655
656     return TRUE;
657 }
658
659
660 /**************************************************************************
661  *                      X11DRV_CLIPBOARD_FreeData
662  *
663  * Free clipboard data handle.
664  */
665 static void X11DRV_CLIPBOARD_FreeData(LPWINE_CLIPDATA lpData)
666 {
667     TRACE("%d\n", lpData->wFormatID);
668
669     if ((lpData->wFormatID >= CF_GDIOBJFIRST &&
670         lpData->wFormatID <= CF_GDIOBJLAST) || 
671         lpData->wFormatID == CF_BITMAP || 
672         lpData->wFormatID == CF_DIB || 
673         lpData->wFormatID == CF_PALETTE)
674     {
675       if (lpData->hData32)
676         DeleteObject(lpData->hData32);
677
678       if (lpData->hData16)
679         DeleteObject(HGDIOBJ_32(lpData->hData16));
680
681       if ((lpData->wFormatID == CF_DIB) && lpData->drvData)
682           XFreePixmap(gdi_display, lpData->drvData);
683     }
684     else if (lpData->wFormatID == CF_METAFILEPICT)
685     {
686       if (lpData->hData32)
687       {
688         DeleteMetaFile(((METAFILEPICT *)GlobalLock( lpData->hData32 ))->hMF );
689         GlobalFree(lpData->hData32);
690
691         if (lpData->hData16)
692           /* HMETAFILE16 and HMETAFILE32 are apparently the same thing,
693              and a shallow copy is enough to share a METAFILEPICT
694              structure between 16bit and 32bit clipboards.  The MetaFile
695              should of course only be deleted once. */
696           GlobalFree16(lpData->hData16);
697       }
698
699       if (lpData->hData16)
700       {
701         METAFILEPICT16* lpMetaPict = (METAFILEPICT16 *) GlobalLock16(lpData->hData16);
702
703         if (lpMetaPict)
704         {
705             DeleteMetaFile16(lpMetaPict->hMF);
706             lpMetaPict->hMF = 0;
707         }
708
709         GlobalFree16(lpData->hData16);
710       }
711     }
712     else if (lpData->wFormatID == CF_ENHMETAFILE)
713     {
714         if (lpData->hData32)
715             DeleteEnhMetaFile(lpData->hData32);
716     }
717     else if (lpData->wFormatID < CF_PRIVATEFIRST ||
718              lpData->wFormatID > CF_PRIVATELAST)
719     {
720       if (lpData->hData32)
721         GlobalFree(lpData->hData32);
722
723       if (lpData->hData16)
724         GlobalFree16(lpData->hData16);
725     }
726
727     lpData->hData16 = 0;
728     lpData->hData32 = 0;
729     lpData->drvData = 0;
730 }
731
732
733 /**************************************************************************
734  *                      X11DRV_CLIPBOARD_UpdateCache
735  */
736 static BOOL X11DRV_CLIPBOARD_UpdateCache(LPCLIPBOARDINFO lpcbinfo)
737 {
738     BOOL bret = TRUE;
739
740     if (!X11DRV_CLIPBOARD_IsSelectionOwner())
741     {
742         if (!X11DRV_CLIPBOARD_GetClipboardInfo(lpcbinfo))
743         {
744             ERR("Failed to retrieve clipboard information.\n");
745             bret = FALSE;
746         }
747         else if (wSeqNo < lpcbinfo->seqno)
748         {
749             X11DRV_EmptyClipboard(TRUE);
750
751             if (X11DRV_CLIPBOARD_QueryAvailableData(lpcbinfo) < 0)
752             {
753                 ERR("Failed to cache clipboard data owned by another process.\n");
754                 bret = FALSE;
755             }
756             else
757             {
758                 X11DRV_EndClipboardUpdate();
759             }
760
761             wSeqNo = lpcbinfo->seqno;
762         }
763     }
764
765     return bret;
766 }
767
768
769 /**************************************************************************
770  *                      X11DRV_CLIPBOARD_RenderFormat
771  */
772 static BOOL X11DRV_CLIPBOARD_RenderFormat(LPWINE_CLIPDATA lpData)
773 {
774     BOOL bret = TRUE;
775
776     TRACE(" 0x%04x hData32(0x%08x) hData16(0x%08x)\n", 
777         lpData->wFormatID, (unsigned int)lpData->hData32, lpData->hData16);
778
779     if (lpData->hData32 || lpData->hData16)
780         return bret; /* Already rendered */
781
782     if (lpData->wFlags & CF_FLAG_SYNTHESIZED)
783         bret = X11DRV_CLIPBOARD_RenderSynthesizedFormat(lpData);
784     else if (!X11DRV_CLIPBOARD_IsSelectionOwner())
785     {
786         if (!X11DRV_CLIPBOARD_ReadClipboardData(lpData->wFormatID))
787         {
788             ERR("Failed to cache clipboard data owned by another process. Format=%d\n", 
789                 lpData->wFormatID);
790             bret = FALSE;
791         }
792     }
793     else
794     {
795         CLIPBOARDINFO cbInfo;
796
797         if (X11DRV_CLIPBOARD_GetClipboardInfo(&cbInfo) && cbInfo.hWndOwner)
798         {
799             /* Send a WM_RENDERFORMAT message to notify the owner to render the
800              * data requested into the clipboard.
801              */
802             TRACE("Sending WM_RENDERFORMAT message to hwnd(%p)\n", cbInfo.hWndOwner);
803             SendMessageW(cbInfo.hWndOwner, WM_RENDERFORMAT, (WPARAM)lpData->wFormatID, 0);
804
805             if (!lpData->hData32 && !lpData->hData16)
806                 bret = FALSE;
807         }
808         else
809         {
810             ERR("hWndClipOwner is lost!\n");
811             bret = FALSE;
812         }
813     }
814
815     return bret;
816 }
817
818
819 /**************************************************************************
820  *                      CLIPBOARD_ConvertText
821  * Returns number of required/converted characters - not bytes!
822  */
823 static INT CLIPBOARD_ConvertText(WORD src_fmt, void const *src, INT src_size,
824                                  WORD dst_fmt, void *dst, INT dst_size)
825 {
826     UINT cp;
827
828     if(src_fmt == CF_UNICODETEXT)
829     {
830         switch(dst_fmt)
831         {
832         case CF_TEXT:
833             cp = CP_ACP;
834             break;
835         case CF_OEMTEXT:
836             cp = CP_OEMCP;
837             break;
838         default:
839             return 0;
840         }
841         return WideCharToMultiByte(cp, 0, src, src_size, dst, dst_size, NULL, NULL);
842     }
843
844     if(dst_fmt == CF_UNICODETEXT)
845     {
846         switch(src_fmt)
847         {
848         case CF_TEXT:
849             cp = CP_ACP;
850             break;
851         case CF_OEMTEXT:
852             cp = CP_OEMCP;
853             break;
854         default:
855             return 0;
856         }
857         return MultiByteToWideChar(cp, 0, src, src_size, dst, dst_size);
858     }
859
860     if(!dst_size) return src_size;
861
862     if(dst_size > src_size) dst_size = src_size;
863
864     if(src_fmt == CF_TEXT )
865         CharToOemBuffA(src, dst, dst_size);
866     else
867         OemToCharBuffA(src, dst, dst_size);
868
869     return dst_size;
870 }
871
872
873 /**************************************************************************
874  *                      X11DRV_CLIPBOARD_RenderSynthesizedFormat
875  */
876 static BOOL X11DRV_CLIPBOARD_RenderSynthesizedFormat(LPWINE_CLIPDATA lpData)
877 {
878     BOOL bret = FALSE;
879
880     TRACE("\n");
881
882     if (lpData->wFlags & CF_FLAG_SYNTHESIZED)
883     {
884         UINT wFormatID = lpData->wFormatID;
885
886         if (wFormatID == CF_UNICODETEXT || wFormatID == CF_TEXT || wFormatID == CF_OEMTEXT)
887             bret = X11DRV_CLIPBOARD_RenderSynthesizedText(wFormatID);
888         else 
889         {
890             switch (wFormatID)
891             {
892                 case CF_DIB:
893                     bret = X11DRV_CLIPBOARD_RenderSynthesizedDIB();
894                     break;
895
896                 case CF_BITMAP:
897                     bret = X11DRV_CLIPBOARD_RenderSynthesizedBitmap();
898                     break;
899
900                 case CF_ENHMETAFILE:
901                 case CF_METAFILEPICT:
902                     FIXME("Synthesizing wFormatID(0x%08x) not implemented\n", wFormatID);
903                     break;
904
905                 default:
906                     FIXME("Called to synthesize unknown format\n");
907                     break;
908             }
909         }
910
911         lpData->wFlags &= ~CF_FLAG_SYNTHESIZED;
912     }
913
914     return bret;
915 }
916
917
918 /**************************************************************************
919  *                      X11DRV_CLIPBOARD_RenderSynthesizedText
920  *
921  * Renders synthesized text
922  */
923 static BOOL X11DRV_CLIPBOARD_RenderSynthesizedText(UINT wFormatID)
924 {
925     LPCSTR lpstrS;
926     LPSTR  lpstrT;
927     HANDLE hData32;
928     INT src_chars, dst_chars, alloc_size;
929     LPWINE_CLIPDATA lpSource = NULL;
930
931     TRACE(" %d\n", wFormatID);
932
933     if ((lpSource = X11DRV_CLIPBOARD_LookupData(wFormatID)) &&
934         lpSource->hData32)
935         return TRUE;
936
937     /* Look for rendered source or non-synthesized source */
938     if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_UNICODETEXT)) &&
939         (!(lpSource->wFlags & CF_FLAG_SYNTHESIZED) || lpSource->hData32))
940     {
941         TRACE("UNICODETEXT -> %d\n", wFormatID);
942     }
943     else if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_TEXT)) &&
944         (!(lpSource->wFlags & CF_FLAG_SYNTHESIZED) || lpSource->hData32))
945     {
946         TRACE("TEXT -> %d\n", wFormatID);
947     }
948     else if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_OEMTEXT)) &&
949         (!(lpSource->wFlags & CF_FLAG_SYNTHESIZED) || lpSource->hData32))
950     {
951         TRACE("OEMTEXT -> %d\n", wFormatID);
952     }
953
954     if (!lpSource || (lpSource->wFlags & CF_FLAG_SYNTHESIZED &&
955         !lpSource->hData32))
956         return FALSE;
957
958     /* Ask the clipboard owner to render the source text if necessary */
959     if (!lpSource->hData32 && !X11DRV_CLIPBOARD_RenderFormat(lpSource))
960         return FALSE;
961
962     if (lpSource->hData32)
963     {
964         lpstrS = (LPSTR)GlobalLock(lpSource->hData32);
965     }
966     else
967     {
968         lpstrS = (LPSTR)GlobalLock16(lpSource->hData16);
969     }
970
971     if (!lpstrS)
972         return FALSE;
973
974     /* Text always NULL terminated */
975     if(lpSource->wFormatID == CF_UNICODETEXT)
976         src_chars = strlenW((LPCWSTR)lpstrS) + 1;
977     else
978         src_chars = strlen(lpstrS) + 1;
979
980     /* Calculate number of characters in the destination buffer */
981     dst_chars = CLIPBOARD_ConvertText(lpSource->wFormatID, lpstrS, 
982         src_chars, wFormatID, NULL, 0);
983
984     if (!dst_chars)
985         return FALSE;
986
987     TRACE("Converting from '%d' to '%d', %i chars\n",
988         lpSource->wFormatID, wFormatID, src_chars);
989
990     /* Convert characters to bytes */
991     if(wFormatID == CF_UNICODETEXT)
992         alloc_size = dst_chars * sizeof(WCHAR);
993     else
994         alloc_size = dst_chars;
995
996     hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | 
997         GMEM_DDESHARE, alloc_size);
998
999     lpstrT = (LPSTR)GlobalLock(hData32);
1000
1001     if (lpstrT)
1002     {
1003         CLIPBOARD_ConvertText(lpSource->wFormatID, lpstrS, src_chars,
1004             wFormatID, lpstrT, dst_chars);
1005         GlobalUnlock(hData32);
1006     }
1007
1008     /* Unlock source */
1009     if (lpSource->hData32)
1010         GlobalUnlock(lpSource->hData32);
1011     else
1012         GlobalUnlock16(lpSource->hData16);
1013
1014     return X11DRV_CLIPBOARD_InsertClipboardData(wFormatID, 0, hData32, 0);
1015 }
1016
1017
1018 /**************************************************************************
1019  *                      X11DRV_CLIPBOARD_RenderSynthesizedDIB
1020  *
1021  * Renders synthesized DIB
1022  */
1023 static BOOL X11DRV_CLIPBOARD_RenderSynthesizedDIB()
1024 {
1025     BOOL bret = FALSE;
1026     LPWINE_CLIPDATA lpSource = NULL;
1027
1028     TRACE("\n");
1029
1030     if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_DIB)) && lpSource->hData32)
1031     {
1032         bret = TRUE;
1033     }
1034     /* If we have a bitmap and it's not synthesized or it has been rendered */
1035     else if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_BITMAP)) &&
1036         (!(lpSource->wFlags & CF_FLAG_SYNTHESIZED) || lpSource->hData32))
1037     {
1038         /* Render source if required */
1039         if (lpSource->hData32 || X11DRV_CLIPBOARD_RenderFormat(lpSource))
1040         {
1041             HDC hdc;
1042             HGLOBAL hData32;
1043
1044             hdc = GetDC(NULL);
1045             hData32 = X11DRV_DIB_CreateDIBFromBitmap(hdc, lpSource->hData32);
1046             ReleaseDC(NULL, hdc);
1047
1048             if (hData32)
1049             {
1050                 X11DRV_CLIPBOARD_InsertClipboardData(CF_DIB, 0, hData32, 0);
1051                 bret = TRUE;
1052             }
1053         }
1054     }
1055
1056     return bret;
1057 }
1058
1059
1060 /**************************************************************************
1061  *                      X11DRV_CLIPBOARD_RenderSynthesizedBitmap
1062  *
1063  * Renders synthesized bitmap
1064  */
1065 static BOOL X11DRV_CLIPBOARD_RenderSynthesizedBitmap()
1066 {
1067     BOOL bret = FALSE;
1068     LPWINE_CLIPDATA lpSource = NULL;
1069
1070     TRACE("\n");
1071
1072     if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_BITMAP)) && lpSource->hData32)
1073     {
1074         bret = TRUE;
1075     }
1076     /* If we have a dib and it's not synthesized or it has been rendered */
1077     else if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_DIB)) &&
1078         (!(lpSource->wFlags & CF_FLAG_SYNTHESIZED) || lpSource->hData32))
1079     {
1080         /* Render source if required */
1081         if (lpSource->hData32 || X11DRV_CLIPBOARD_RenderFormat(lpSource))
1082         {
1083             HDC hdc;
1084             HBITMAP hData32;
1085             unsigned int offset;
1086             LPBITMAPINFOHEADER lpbmih;
1087
1088             hdc = GetDC(NULL);
1089             lpbmih = (LPBITMAPINFOHEADER) GlobalLock(lpSource->hData32);
1090
1091             offset = sizeof(BITMAPINFOHEADER)
1092                   + ((lpbmih->biBitCount <= 8) ? (sizeof(RGBQUAD) *
1093                     (1 << lpbmih->biBitCount)) : 0);
1094
1095             hData32 = CreateDIBitmap(hdc, lpbmih, CBM_INIT, (LPBYTE)lpbmih +
1096                 offset, (LPBITMAPINFO) lpbmih, DIB_RGB_COLORS);
1097
1098             GlobalUnlock(lpSource->hData32);
1099             ReleaseDC(NULL, hdc);
1100
1101             if (hData32)
1102             {
1103                 X11DRV_CLIPBOARD_InsertClipboardData(CF_BITMAP, 0, hData32, 0);
1104                 bret = TRUE;
1105             }
1106         }
1107     }
1108
1109     return bret;
1110 }
1111
1112
1113 /**************************************************************************
1114  *              X11DRV_CLIPBOARD_ImportXAString
1115  *
1116  *  Import XA_STRING, converting the string to CF_UNICODE.
1117  */
1118 HANDLE X11DRV_CLIPBOARD_ImportXAString(LPBYTE lpdata, UINT cBytes)
1119 {
1120     LPSTR lpstr;
1121     UINT i, inlcount = 0;
1122     HANDLE hUnicodeText = 0;
1123
1124     for (i = 0; i <= cBytes; i++)
1125     {
1126         if (lpdata[i] == '\n')
1127             inlcount++;
1128     }
1129
1130     if ((lpstr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cBytes + inlcount + 1)))
1131     {
1132         UINT count;
1133
1134         for (i = 0, inlcount = 0; i <= cBytes; i++)
1135         {
1136             if (lpdata[i] == '\n')
1137                 lpstr[inlcount++] = '\r';
1138
1139             lpstr[inlcount++] = lpdata[i];
1140         }
1141
1142         count = MultiByteToWideChar(CP_UNIXCP, 0, lpstr, -1, NULL, 0);
1143         hUnicodeText = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, count * sizeof(WCHAR));
1144
1145         if(hUnicodeText)
1146         {
1147             WCHAR *textW = GlobalLock(hUnicodeText);
1148             MultiByteToWideChar(CP_UNIXCP, 0, lpstr, -1, textW, count);
1149             GlobalUnlock(hUnicodeText);
1150         }
1151
1152         HeapFree(GetProcessHeap(), 0, lpstr);
1153     }
1154
1155     return hUnicodeText;
1156 }
1157
1158
1159 /**************************************************************************
1160  *              X11DRV_CLIPBOARD_ImportXAPIXMAP
1161  *
1162  *  Import XA_PIXMAP, converting the image to CF_DIB.
1163  */
1164 HANDLE X11DRV_CLIPBOARD_ImportXAPIXMAP(LPBYTE lpdata, UINT cBytes)
1165 {
1166     HANDLE hTargetImage = 0;  /* Handle to store the converted DIB */
1167     Pixmap *pPixmap = (Pixmap *) lpdata;
1168     HWND hwnd = GetOpenClipboardWindow();
1169     HDC hdc = GetDC(hwnd);
1170
1171     hTargetImage = X11DRV_DIB_CreateDIBFromPixmap(*pPixmap, hdc, TRUE);
1172
1173     ReleaseDC(hwnd, hdc);
1174
1175     return hTargetImage;
1176 }
1177
1178
1179 /**************************************************************************
1180  *              X11DRV_CLIPBOARD_ImportMetaFilePict
1181  *
1182  *  Import MetaFilePict.
1183  */
1184 HANDLE X11DRV_CLIPBOARD_ImportMetaFilePict(LPBYTE lpdata, UINT cBytes)
1185 {
1186     return X11DRV_CLIPBOARD_SerializeMetafile(CF_METAFILEPICT, (HANDLE)lpdata, (LPDWORD)&cBytes, FALSE);
1187 }
1188
1189
1190 /**************************************************************************
1191  *              X11DRV_ImportEnhMetaFile
1192  *
1193  *  Import EnhMetaFile.
1194  */
1195 HANDLE X11DRV_CLIPBOARD_ImportEnhMetaFile(LPBYTE lpdata, UINT cBytes)
1196 {
1197     return X11DRV_CLIPBOARD_SerializeMetafile(CF_ENHMETAFILE, (HANDLE)lpdata, (LPDWORD)&cBytes, FALSE);
1198 }
1199
1200
1201 /**************************************************************************
1202  *              X11DRV_ImportClipbordaData
1203  *
1204  *  Generic import clipboard data routine.
1205  */
1206 HANDLE X11DRV_CLIPBOARD_ImportClipboardData(LPBYTE lpdata, UINT cBytes)
1207 {
1208     LPVOID lpClipData;
1209     HANDLE hClipData = 0;
1210
1211     if (cBytes)
1212     {
1213         /* Turn on the DDESHARE flag to enable shared 32 bit memory */
1214         hClipData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, cBytes);
1215         if ((lpClipData = GlobalLock(hClipData)))
1216         {
1217             memcpy(lpClipData, lpdata, cBytes);
1218             GlobalUnlock(hClipData);
1219         }
1220         else
1221             hClipData = 0;
1222     }
1223
1224     return hClipData;
1225 }
1226
1227
1228 /**************************************************************************
1229                 X11DRV_CLIPBOARD_ExportClipboardData
1230  *
1231  *  Generic export clipboard data routine.
1232  */
1233 HANDLE X11DRV_CLIPBOARD_ExportClipboardData(Window requestor, Atom aTarget,
1234     Atom rprop, LPWINE_CLIPDATA lpData, LPDWORD lpBytes)
1235 {
1236     LPVOID lpClipData;
1237     UINT cBytes = 0;
1238     HANDLE hClipData = 0;
1239
1240     *lpBytes = 0; /* Assume failure */
1241
1242     if (!X11DRV_CLIPBOARD_RenderFormat(lpData))
1243         ERR("Failed to export %d format\n", lpData->wFormatID);
1244     else
1245     {
1246         cBytes = GlobalSize(lpData->hData32);
1247
1248         hClipData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, cBytes);
1249
1250         if ((lpClipData = GlobalLock(hClipData)))
1251         {
1252             LPVOID lpdata = GlobalLock(lpData->hData32);
1253
1254             memcpy(lpClipData, lpdata, cBytes);
1255             *lpBytes = cBytes;
1256
1257             GlobalUnlock(lpData->hData32);
1258             GlobalUnlock(hClipData);
1259         }
1260     }
1261
1262     return hClipData;
1263 }
1264
1265
1266 /**************************************************************************
1267  *              X11DRV_CLIPBOARD_ExportXAString
1268  *
1269  *  Export CF_UNICODE converting the string to XA_STRING.
1270  *  Helper function for X11DRV_CLIPBOARD_ExportString.
1271  */
1272 HANDLE X11DRV_CLIPBOARD_ExportXAString(LPWINE_CLIPDATA lpData, LPDWORD lpBytes)
1273 {
1274     UINT i, j;
1275     UINT size;
1276     LPWSTR uni_text;
1277     LPSTR text, lpstr;
1278
1279     *lpBytes = 0; /* Assume return has zero bytes */
1280
1281     uni_text = GlobalLock(lpData->hData32);
1282
1283     size = WideCharToMultiByte(CP_UNIXCP, 0, uni_text, -1, NULL, 0, NULL, NULL);
1284
1285     text = HeapAlloc(GetProcessHeap(), 0, size);
1286     if (!text)
1287        return None;
1288     WideCharToMultiByte(CP_UNIXCP, 0, uni_text, -1, text, size, NULL, NULL);
1289
1290     /* remove carriage returns */
1291
1292     lpstr = (char*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size-- );
1293     if(lpstr == NULL) return None;
1294     for(i = 0,j = 0; i < size && text[i]; i++ )
1295     {
1296         if( text[i] == '\r' &&
1297             (text[i+1] == '\n' || text[i+1] == '\0') ) continue;
1298         lpstr[j++] = text[i];
1299     }
1300     lpstr[j]='\0';
1301
1302     *lpBytes = j; /* Number of bytes in string */
1303
1304     HeapFree(GetProcessHeap(), 0, text);
1305     GlobalUnlock(lpData->hData32);
1306
1307     return lpstr;
1308 }
1309
1310
1311 /**************************************************************************
1312  *              X11DRV_CLIPBOARD_ExportCompoundText
1313  *
1314  *  Export CF_UNICODE to COMPOUND_TEXT or TEXT
1315  *  Helper function for X11DRV_CLIPBOARD_ExportString.
1316  */
1317 HANDLE X11DRV_CLIPBOARD_ExportCompoundText(Window requestor, Atom aTarget, Atom rprop,
1318     LPWINE_CLIPDATA lpData, LPDWORD lpBytes)
1319 {
1320     Display *display = thread_display();
1321     char* lpstr = 0;
1322     XTextProperty prop;
1323     XICCEncodingStyle style;
1324
1325     lpstr = (char*) X11DRV_CLIPBOARD_ExportXAString(lpData, lpBytes);
1326
1327     if (lpstr)
1328     {
1329         if (aTarget == x11drv_atom(COMPOUND_TEXT))
1330            style = XCompoundTextStyle;
1331         else
1332            style = XStdICCTextStyle;
1333
1334         /* Update the X property */
1335         wine_tsx11_lock();
1336         if (XmbTextListToTextProperty(display, &lpstr, 1, style, &prop) == Success)
1337         {
1338            XSetTextProperty(display, requestor, &prop, rprop);
1339            XFree(prop.value);
1340         }
1341         wine_tsx11_unlock();
1342
1343         HeapFree( GetProcessHeap(), 0, lpstr );
1344     }
1345
1346     return 0;
1347 }
1348
1349 /**************************************************************************
1350  *              X11DRV_CLIPBOARD_ExportString
1351  *
1352  *  Export CF_UNICODE string
1353  */
1354 HANDLE X11DRV_CLIPBOARD_ExportString(Window requestor, Atom aTarget, Atom rprop,
1355     LPWINE_CLIPDATA lpData, LPDWORD lpBytes)
1356 {
1357     if (X11DRV_CLIPBOARD_RenderFormat(lpData))
1358     {
1359         if (aTarget == XA_STRING)
1360             return X11DRV_CLIPBOARD_ExportXAString(lpData, lpBytes);
1361         else if (aTarget == x11drv_atom(COMPOUND_TEXT) || aTarget == x11drv_atom(TEXT))
1362             return X11DRV_CLIPBOARD_ExportCompoundText(requestor, aTarget,
1363                 rprop, lpData, lpBytes);
1364         else
1365             ERR("Unknown target %ld to %d format\n", aTarget, lpData->wFormatID);
1366     }
1367     else
1368         ERR("Failed to render %d format\n", lpData->wFormatID);
1369
1370     return 0;
1371 }
1372
1373
1374 /**************************************************************************
1375  *              X11DRV_CLIPBOARD_ExportXAPIXMAP
1376  *
1377  *  Export CF_DIB to XA_PIXMAP.
1378  */
1379 HANDLE X11DRV_CLIPBOARD_ExportXAPIXMAP(Window requestor, Atom aTarget, Atom rprop,
1380     LPWINE_CLIPDATA lpdata, LPDWORD lpBytes)
1381 {
1382     HDC hdc;
1383     HANDLE hData;
1384     unsigned char* lpData;
1385
1386     if (!X11DRV_CLIPBOARD_RenderFormat(lpdata))
1387     {
1388         ERR("Failed to export %d format\n", lpdata->wFormatID);
1389         return 0;
1390     }
1391
1392     if (!lpdata->drvData) /* If not already rendered */
1393     {
1394         /* For convert from packed DIB to Pixmap */
1395         hdc = GetDC(0);
1396         lpdata->drvData = (UINT) X11DRV_DIB_CreatePixmapFromDIB(lpdata->hData32, hdc);
1397         ReleaseDC(0, hdc);
1398     }
1399
1400     *lpBytes = sizeof(Pixmap); /* pixmap is a 32bit value */
1401
1402     /* Wrap pixmap so we can return a handle */
1403     hData = GlobalAlloc(0, *lpBytes);
1404     lpData = GlobalLock(hData);
1405     memcpy(lpData, &lpdata->drvData, *lpBytes);
1406     GlobalUnlock(hData);
1407
1408     return (HANDLE) hData;
1409 }
1410
1411
1412 /**************************************************************************
1413  *              X11DRV_CLIPBOARD_ExportMetaFilePict
1414  *
1415  *  Export MetaFilePict.
1416  */
1417 HANDLE X11DRV_CLIPBOARD_ExportMetaFilePict(Window requestor, Atom aTarget, Atom rprop,
1418     LPWINE_CLIPDATA lpdata, LPDWORD lpBytes)
1419 {
1420     if (!X11DRV_CLIPBOARD_RenderFormat(lpdata))
1421     {
1422         ERR("Failed to export %d format\n", lpdata->wFormatID);
1423         return 0;
1424     }
1425
1426     return X11DRV_CLIPBOARD_SerializeMetafile(CF_METAFILEPICT, (HANDLE)lpdata->hData32, 
1427         lpBytes, TRUE);
1428 }
1429
1430
1431 /**************************************************************************
1432  *              X11DRV_CLIPBOARD_ExportEnhMetaFile
1433  *
1434  *  Export EnhMetaFile.
1435  */
1436 HANDLE X11DRV_CLIPBOARD_ExportEnhMetaFile(Window requestor, Atom aTarget, Atom rprop,
1437     LPWINE_CLIPDATA lpdata, LPDWORD lpBytes)
1438 {
1439     if (!X11DRV_CLIPBOARD_RenderFormat(lpdata))
1440     {
1441         ERR("Failed to export %d format\n", lpdata->wFormatID);
1442         return 0;
1443     }
1444
1445     return X11DRV_CLIPBOARD_SerializeMetafile(CF_ENHMETAFILE, (HANDLE)lpdata->hData32, 
1446         lpBytes, TRUE);
1447 }
1448
1449
1450 /**************************************************************************
1451  *              X11DRV_CLIPBOARD_QueryTargets
1452  */
1453 static BOOL X11DRV_CLIPBOARD_QueryTargets(Display *display, Window w, Atom selection,
1454     Atom target, XEvent *xe)
1455 {
1456     INT i;
1457     Bool res;
1458
1459     wine_tsx11_lock();
1460     XConvertSelection(display, selection, target,
1461         x11drv_atom(SELECTION_DATA), w, CurrentTime);
1462     wine_tsx11_unlock();
1463
1464     /*
1465      * Wait until SelectionNotify is received
1466      */
1467     for (i = 0; i < SELECTION_RETRIES; i++)
1468     {
1469         wine_tsx11_lock();
1470         res = XCheckTypedWindowEvent(display, w, SelectionNotify, xe);
1471         wine_tsx11_unlock();
1472         if (res && xe->xselection.selection == selection) break;
1473
1474         usleep(SELECTION_WAIT);
1475     }
1476
1477     /* Verify that the selection returned a valid TARGETS property */
1478     if ((xe->xselection.target != target) || (xe->xselection.property == None))
1479     {
1480         /* Selection owner failed to respond or we missed the SelectionNotify */
1481         WARN("Failed to retrieve TARGETS for selection %ld.\n", selection);
1482         return FALSE;
1483     }
1484
1485     return TRUE;
1486 }
1487
1488
1489 /**************************************************************************
1490  *              X11DRV_CLIPBOARD_InsertSelectionProperties
1491  *
1492  * Mark property available for future retrieval.
1493  */
1494 static VOID X11DRV_CLIPBOARD_InsertSelectionProperties(Display *display, Atom* properties, UINT count)
1495 {
1496      UINT i, nb_atoms = 0;
1497      Atom *atoms = NULL;
1498
1499      /* Cache these formats in the clipboard cache */
1500      for (i = 0; i < count; i++)
1501      {
1502          LPWINE_CLIPFORMAT lpFormat = X11DRV_CLIPBOARD_LookupProperty(properties[i]);
1503
1504          if (!lpFormat)
1505              lpFormat = X11DRV_CLIPBOARD_LookupAliasProperty(properties[i]);
1506
1507          if (!lpFormat)
1508          {
1509              /* add it to the list of atoms that we don't know about yet */
1510              if (!atoms) atoms = HeapAlloc( GetProcessHeap(), 0,
1511                                             (count - i) * sizeof(*atoms) );
1512              if (atoms) atoms[nb_atoms++] = properties[i];
1513          }
1514          else
1515          {
1516              TRACE("Atom#%d Property(%d): --> FormatID(%d) %s\n",
1517                    i, lpFormat->drvData, lpFormat->wFormatID, debugstr_w(lpFormat->Name));
1518              X11DRV_CLIPBOARD_InsertClipboardData(lpFormat->wFormatID, 0, 0, 0);
1519          }
1520      }
1521
1522      /* query all unknown atoms in one go */
1523      if (atoms)
1524      {
1525          char **names = HeapAlloc( GetProcessHeap(), 0, nb_atoms * sizeof(*names) );
1526          if (names)
1527          {
1528              wine_tsx11_lock();
1529              XGetAtomNames( display, atoms, nb_atoms, names );
1530              wine_tsx11_unlock();
1531              for (i = 0; i < nb_atoms; i++)
1532              {
1533                  WINE_CLIPFORMAT *lpFormat;
1534                  LPWSTR wname;
1535                  int len = MultiByteToWideChar(CP_UNIXCP, 0, names[i], -1, NULL, 0);
1536                  wname = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
1537                  MultiByteToWideChar(CP_UNIXCP, 0, names[i], -1, wname, len);
1538
1539                  lpFormat = register_format( wname, atoms[i] );
1540                  HeapFree(GetProcessHeap(), 0, wname);
1541                  if (!lpFormat)
1542                  {
1543                      ERR("Failed to register %s property. Type will not be cached.\n", names[i]);
1544                      continue;
1545                  }
1546                  TRACE("Atom#%d Property(%d): --> FormatID(%d) %s\n",
1547                        i, lpFormat->drvData, lpFormat->wFormatID, debugstr_w(lpFormat->Name));
1548                  X11DRV_CLIPBOARD_InsertClipboardData(lpFormat->wFormatID, 0, 0, 0);
1549              }
1550              wine_tsx11_lock();
1551              for (i = 0; i < nb_atoms; i++) XFree( names[i] );
1552              wine_tsx11_unlock();
1553              HeapFree( GetProcessHeap(), 0, names );
1554          }
1555          HeapFree( GetProcessHeap(), 0, atoms );
1556      }
1557 }
1558
1559
1560 /**************************************************************************
1561  *              X11DRV_CLIPBOARD_QueryAvailableData
1562  *
1563  * Caches the list of data formats available from the current selection.
1564  * This queries the selection owner for the TARGETS property and saves all
1565  * reported property types.
1566  */
1567 static int X11DRV_CLIPBOARD_QueryAvailableData(LPCLIPBOARDINFO lpcbinfo)
1568 {
1569     Display *display = thread_display();
1570     XEvent         xe;
1571     Atom           atype=AnyPropertyType;
1572     int            aformat;
1573     unsigned long  remain;
1574     Atom*          targetList=NULL;
1575     Window         w;
1576     HWND           hWndClipWindow; 
1577     unsigned long  cSelectionTargets = 0;
1578
1579     if (selectionAcquired & (S_PRIMARY | S_CLIPBOARD))
1580     {
1581         ERR("Received request to cache selection but process is owner=(%08x)\n", 
1582             (unsigned) selectionWindow);
1583
1584         selectionAcquired  = S_NOSELECTION;
1585
1586         wine_tsx11_lock();
1587         if (XGetSelectionOwner(display,XA_PRIMARY) == selectionWindow)
1588             selectionAcquired |= S_PRIMARY;
1589
1590         if (XGetSelectionOwner(display,x11drv_atom(CLIPBOARD)) == selectionWindow)
1591             selectionAcquired |= S_CLIPBOARD;
1592         wine_tsx11_unlock();
1593
1594         if (!(selectionAcquired == (S_PRIMARY | S_CLIPBOARD)))
1595         {
1596             WARN("Lost selection but process didn't process SelectClear\n");
1597             selectionWindow = None;
1598         }
1599         else
1600         {
1601             return -1; /* Prevent self request */
1602         }
1603     }
1604
1605     if (lpcbinfo->flags & CB_OWNER)
1606         hWndClipWindow = lpcbinfo->hWndOwner;
1607     else if (lpcbinfo->flags & CB_OPEN)
1608         hWndClipWindow = lpcbinfo->hWndOpen;
1609     else
1610         hWndClipWindow = GetActiveWindow();
1611
1612     if (!hWndClipWindow)
1613     {
1614         WARN("No window available to retrieve selection!\n");
1615         return -1;
1616     }
1617
1618     w = X11DRV_get_whole_window(GetAncestor(hWndClipWindow, GA_ROOT));
1619
1620     /*
1621      * Query the selection owner for the TARGETS property
1622      */
1623     wine_tsx11_lock();
1624     if ((usePrimary && XGetSelectionOwner(display,XA_PRIMARY)) ||
1625         XGetSelectionOwner(display,x11drv_atom(CLIPBOARD)))
1626     {
1627         wine_tsx11_unlock();
1628         if (usePrimary && (X11DRV_CLIPBOARD_QueryTargets(display, w, XA_PRIMARY, x11drv_atom(TARGETS), &xe)))
1629             selectionCacheSrc = XA_PRIMARY;
1630         else if (X11DRV_CLIPBOARD_QueryTargets(display, w, x11drv_atom(CLIPBOARD), x11drv_atom(TARGETS), &xe))
1631             selectionCacheSrc = x11drv_atom(CLIPBOARD);
1632         else
1633         {
1634             Atom xstr = XA_PRIMARY;
1635
1636             /* Selection Owner doesn't understand TARGETS, try retrieving XA_STRING */
1637             if (X11DRV_CLIPBOARD_QueryTargets(display, w, XA_PRIMARY, XA_STRING, &xe))
1638             {
1639                 X11DRV_CLIPBOARD_InsertSelectionProperties(display, &xstr, 1);
1640                 selectionCacheSrc = XA_PRIMARY;
1641                 return 1;
1642             }
1643             else if (X11DRV_CLIPBOARD_QueryTargets(display, w, x11drv_atom(CLIPBOARD), XA_STRING, &xe))
1644             {
1645                 X11DRV_CLIPBOARD_InsertSelectionProperties(display, &xstr, 1);
1646                 selectionCacheSrc = x11drv_atom(CLIPBOARD);
1647                 return 1;
1648             }
1649             else
1650             {
1651                 WARN("Failed to query selection owner for available data.\n");
1652                 return -1;
1653             }
1654         }
1655     }
1656     else /* No selection owner so report 0 targets available */
1657     {
1658         wine_tsx11_unlock();
1659         return 0;
1660     }
1661
1662     /* Read the TARGETS property contents */
1663     wine_tsx11_lock();
1664     if(XGetWindowProperty(display, xe.xselection.requestor, xe.xselection.property,
1665         0, 0x3FFF, True, AnyPropertyType/*XA_ATOM*/, &atype, &aformat, &cSelectionTargets, 
1666         &remain, (unsigned char**)&targetList) != Success)
1667     {
1668         wine_tsx11_unlock();
1669         WARN("Failed to read TARGETS property\n");
1670     }
1671     else
1672     {
1673         wine_tsx11_unlock();
1674        TRACE("Type %lx,Format %d,nItems %ld, Remain %ld\n",
1675              atype, aformat, cSelectionTargets, remain);
1676        /*
1677         * The TARGETS property should have returned us a list of atoms
1678         * corresponding to each selection target format supported.
1679         */
1680        if ((atype == XA_ATOM || atype == x11drv_atom(TARGETS)) && aformat == 32)
1681            X11DRV_CLIPBOARD_InsertSelectionProperties(display, targetList, cSelectionTargets);
1682
1683        /* Free the list of targets */
1684        wine_tsx11_lock();
1685        XFree(targetList);
1686        wine_tsx11_unlock();
1687     }
1688
1689     return cSelectionTargets;
1690 }
1691
1692
1693 /**************************************************************************
1694  *      X11DRV_CLIPBOARD_ReadClipboardData
1695  *
1696  * This method is invoked only when we DO NOT own the X selection
1697  *
1698  * We always get the data from the selection client each time,
1699  * since we have no way of determining if the data in our cache is stale.
1700  */
1701 static BOOL X11DRV_CLIPBOARD_ReadClipboardData(UINT wFormat)
1702 {
1703     Display *display = thread_display();
1704     BOOL bRet = FALSE;
1705     Bool res;
1706
1707     HWND hWndClipWindow = GetOpenClipboardWindow();
1708     HWND hWnd = (hWndClipWindow) ? hWndClipWindow : GetActiveWindow();
1709
1710     LPWINE_CLIPFORMAT lpFormat;
1711
1712     TRACE("%d\n", wFormat);
1713
1714     if (!selectionAcquired)
1715     {
1716         Window w = X11DRV_get_whole_window(GetAncestor(hWnd, GA_ROOT));
1717         if(!w)
1718         {
1719             FIXME("No parent win found %p %p\n", hWnd, hWndClipWindow);
1720             return FALSE;
1721         }
1722
1723         lpFormat = X11DRV_CLIPBOARD_LookupFormat(wFormat);
1724
1725         if (lpFormat && lpFormat->drvData)
1726         {
1727             DWORD i;
1728             UINT alias;
1729             XEvent xe;
1730
1731             TRACE("Requesting %s selection (%d) from win(%08x)\n", 
1732                 debugstr_w(lpFormat->Name), lpFormat->drvData, (UINT)selectionCacheSrc);
1733
1734             wine_tsx11_lock();
1735             XConvertSelection(display, selectionCacheSrc, lpFormat->drvData,
1736                               x11drv_atom(SELECTION_DATA), w, CurrentTime);
1737             wine_tsx11_unlock();
1738
1739             /* wait until SelectionNotify is received */
1740             for (i = 0; i < SELECTION_RETRIES; i++)
1741             {
1742                 wine_tsx11_lock();
1743                 res = XCheckTypedWindowEvent(display, w, SelectionNotify, &xe);
1744                 wine_tsx11_unlock();
1745                 if (res && xe.xselection.selection == selectionCacheSrc) break;
1746
1747                 usleep(SELECTION_WAIT);
1748             }
1749
1750             /* If the property wasn't available check for aliases */
1751             if (xe.xselection.property == None &&
1752                 (alias = X11DRV_CLIPBOARD_LookupPropertyAlias(lpFormat->drvData)))
1753             {
1754                 wine_tsx11_lock();
1755                 XConvertSelection(display, selectionCacheSrc, alias,
1756                                   x11drv_atom(SELECTION_DATA), w, CurrentTime);
1757                 wine_tsx11_unlock();
1758
1759                 /* wait until SelectionNotify is received */
1760                 for (i = 0; i < SELECTION_RETRIES; i++)
1761                 {
1762                     wine_tsx11_lock();
1763                     res = XCheckTypedWindowEvent(display, w, SelectionNotify, &xe);
1764                     wine_tsx11_unlock();
1765                     if (res && xe.xselection.selection == selectionCacheSrc) break;
1766
1767                     usleep(SELECTION_WAIT);
1768                 }
1769             }
1770
1771             /* Verify that the selection returned a valid TARGETS property */
1772             if (xe.xselection.property != None)
1773             {
1774                 /*
1775                  *  Read the contents of the X selection property 
1776                  *  into WINE's clipboard cache converting the 
1777                  *  selection to be compatible if possible.
1778                  */
1779                 bRet = X11DRV_CLIPBOARD_ReadSelection(lpFormat, xe.xselection.requestor, 
1780                     xe.xselection.property);
1781             }
1782         }
1783     }
1784     else
1785     {
1786         ERR("Received request to cache selection data but process is owner\n");
1787     }
1788
1789     TRACE("Returning %d\n", bRet);
1790
1791     return bRet;
1792 }
1793
1794
1795 /**************************************************************************
1796  *              X11DRV_CLIPBOARD_ReadSelection
1797  *  Reads the contents of the X selection property into the WINE clipboard cache
1798  *  converting the selection into a format compatible with the windows clipboard
1799  *  if possible.
1800  *  This method is invoked only to read the contents of a the selection owned
1801  *  by an external application. i.e. when we do not own the X selection.
1802  */
1803 static BOOL X11DRV_CLIPBOARD_ReadSelection(LPWINE_CLIPFORMAT lpData, Window w, Atom prop)
1804 {
1805     Display *display = thread_display();
1806     Atom              atype=AnyPropertyType;
1807     int               aformat;
1808     unsigned long     total,nitems,remain,val_cnt;
1809     long              reqlen, bwc;
1810     unsigned char*    val;
1811     unsigned char*    buffer;
1812     BOOL              bRet = FALSE;
1813
1814     if(prop == None)
1815         return bRet;
1816
1817     TRACE("Reading X selection type %s\n", debugstr_w(lpData->Name));
1818
1819     /*
1820      * First request a zero length in order to figure out the request size.
1821      */
1822     wine_tsx11_lock();
1823     if(XGetWindowProperty(display,w,prop,0,0,False, AnyPropertyType,
1824         &atype, &aformat, &nitems, &remain, &buffer) != Success)
1825     {
1826         wine_tsx11_unlock();
1827         WARN("Failed to get property size\n");
1828         return bRet;
1829     }
1830
1831     /* Free zero length return data if any */
1832     if (buffer)
1833     {
1834        XFree(buffer);
1835        buffer = NULL;
1836     }
1837
1838     bwc = aformat/8;
1839     reqlen = remain * bwc;
1840
1841     TRACE("Retrieving %ld bytes\n", reqlen);
1842
1843     val = (char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, reqlen);
1844
1845     /* Read property in 4K blocks */
1846     for (total = 0, val_cnt = 0; remain;)
1847     {
1848        if (XGetWindowProperty(display, w, prop, (total / 4), 4096, False,
1849            AnyPropertyType, &atype, &aformat, &nitems, &remain, &buffer) != Success)
1850        {
1851            wine_tsx11_unlock();
1852            WARN("Failed to read property\n");
1853            HeapFree(GetProcessHeap(), 0, val);
1854            return bRet;
1855        }
1856
1857        bwc = aformat/8;
1858        memcpy(&val[val_cnt], buffer, nitems * bwc);
1859        val_cnt += nitems * bwc;
1860        total += nitems*bwc;
1861        XFree(buffer);
1862     }
1863     wine_tsx11_unlock();
1864
1865     bRet = X11DRV_CLIPBOARD_InsertClipboardData(lpData->wFormatID, 0, lpData->lpDrvImportFunc(val, total), 0);
1866
1867     /* Delete the property on the window now that we are done
1868      * This will send a PropertyNotify event to the selection owner. */
1869     wine_tsx11_lock();
1870     XDeleteProperty(display,w,prop);
1871     wine_tsx11_unlock();
1872
1873     /* Free the retrieved property data */
1874     HeapFree(GetProcessHeap(),0,val);
1875
1876     return bRet;
1877 }
1878
1879
1880 /**************************************************************************
1881  *              CLIPBOARD_SerializeMetafile
1882  */
1883 static HANDLE X11DRV_CLIPBOARD_SerializeMetafile(INT wformat, HANDLE hdata, LPDWORD lpcbytes, BOOL out)
1884 {
1885     HANDLE h = 0;
1886
1887     TRACE(" wFormat=%d hdata=%08x out=%d\n", wformat, (unsigned int) hdata, out);
1888
1889     if (out) /* Serialize out, caller should free memory */
1890     {
1891         *lpcbytes = 0; /* Assume failure */
1892
1893         if (wformat == CF_METAFILEPICT)
1894         {
1895             LPMETAFILEPICT lpmfp = (LPMETAFILEPICT) GlobalLock(hdata);
1896             unsigned int size = GetMetaFileBitsEx(lpmfp->hMF, 0, NULL);
1897
1898             h = GlobalAlloc(0, size + sizeof(METAFILEPICT));
1899             if (h)
1900             {
1901                 char *pdata = GlobalLock(h);
1902
1903                 memcpy(pdata, lpmfp, sizeof(METAFILEPICT));
1904                 GetMetaFileBitsEx(lpmfp->hMF, size, pdata + sizeof(METAFILEPICT));
1905
1906                 *lpcbytes = size + sizeof(METAFILEPICT);
1907
1908                 GlobalUnlock(h);
1909             }
1910
1911             GlobalUnlock(hdata);
1912         }
1913         else if (wformat == CF_ENHMETAFILE)
1914         {
1915             int size = GetEnhMetaFileBits(hdata, 0, NULL);
1916
1917             h = GlobalAlloc(0, size);
1918             if (h)
1919             {
1920                 LPVOID pdata = GlobalLock(h);
1921
1922                 GetEnhMetaFileBits(hdata, size, pdata);
1923                 *lpcbytes = size;
1924
1925                 GlobalUnlock(h);
1926             }
1927         }
1928     }
1929     else
1930     {
1931         if (wformat == CF_METAFILEPICT)
1932         {
1933             h = GlobalAlloc(0, sizeof(METAFILEPICT));
1934             if (h)
1935             {
1936                 unsigned int wiresize, size;
1937                 LPMETAFILEPICT lpmfp = (LPMETAFILEPICT) GlobalLock(h);
1938
1939                 memcpy(lpmfp, (LPVOID)hdata, sizeof(METAFILEPICT));
1940                 wiresize = *lpcbytes - sizeof(METAFILEPICT);
1941                 lpmfp->hMF = SetMetaFileBitsEx(wiresize,
1942                     ((char *)hdata) + sizeof(METAFILEPICT));
1943                 size = GetMetaFileBitsEx(lpmfp->hMF, 0, NULL);
1944                 GlobalUnlock(h);
1945             }
1946         }
1947         else if (wformat == CF_ENHMETAFILE)
1948         {
1949             h = SetEnhMetaFileBits(*lpcbytes, (LPVOID)hdata);
1950         }
1951     }
1952
1953     return h;
1954 }
1955
1956
1957 /**************************************************************************
1958  *              X11DRV_CLIPBOARD_ReleaseSelection
1959  *
1960  * Release XA_CLIPBOARD and XA_PRIMARY in response to a SelectionClear event.
1961  */
1962 void X11DRV_CLIPBOARD_ReleaseSelection(Atom selType, Window w, HWND hwnd, Time time)
1963 {
1964     Display *display = thread_display();
1965
1966     /* w is the window that lost the selection
1967      */
1968     TRACE("event->window = %08x (selectionWindow = %08x) selectionAcquired=0x%08x\n",
1969           (unsigned)w, (unsigned)selectionWindow, (unsigned)selectionAcquired);
1970
1971     if (selectionAcquired && (w == selectionWindow))
1972     {
1973         CLIPBOARDINFO cbinfo;
1974
1975         /* completely give up the selection */
1976         TRACE("Lost CLIPBOARD (+PRIMARY) selection\n");
1977
1978         X11DRV_CLIPBOARD_GetClipboardInfo(&cbinfo);
1979
1980         if (cbinfo.flags & CB_OWNER)
1981         {
1982             /* Since we're still the owner, this wasn't initiated by 
1983                another Wine process */
1984             if (OpenClipboard(hwnd))
1985             {
1986                 /* Destroy private objects */
1987                 SendMessageW(cbinfo.hWndOwner, WM_DESTROYCLIPBOARD, 0, 0);
1988
1989                 /* Give up ownership of the windows clipboard */
1990                 X11DRV_CLIPBOARD_ReleaseOwnership();
1991                 CloseClipboard();
1992             }
1993         }
1994
1995         if ((selType == x11drv_atom(CLIPBOARD)) && (selectionAcquired & S_PRIMARY))
1996         {
1997             TRACE("Lost clipboard. Check if we need to release PRIMARY\n");
1998
1999             wine_tsx11_lock();
2000             if (selectionWindow == XGetSelectionOwner(display, XA_PRIMARY))
2001             {
2002                 TRACE("We still own PRIMARY. Releasing PRIMARY.\n");
2003                 XSetSelectionOwner(display, XA_PRIMARY, None, time);
2004             }
2005             else
2006                 TRACE("We no longer own PRIMARY\n");
2007             wine_tsx11_unlock();
2008         }
2009         else if ((selType == XA_PRIMARY) && (selectionAcquired & S_CLIPBOARD))
2010         {
2011             TRACE("Lost PRIMARY. Check if we need to release CLIPBOARD\n");
2012
2013             wine_tsx11_lock();
2014             if (selectionWindow == XGetSelectionOwner(display,x11drv_atom(CLIPBOARD)))
2015             {
2016                 TRACE("We still own CLIPBOARD. Releasing CLIPBOARD.\n");
2017                 XSetSelectionOwner(display, x11drv_atom(CLIPBOARD), None, time);
2018             }
2019             else
2020                 TRACE("We no longer own CLIPBOARD\n");
2021             wine_tsx11_unlock();
2022         }
2023
2024         selectionWindow = None;
2025
2026         X11DRV_EmptyClipboard(FALSE);
2027
2028         /* Reset the selection flags now that we are done */
2029         selectionAcquired = S_NOSELECTION;
2030     }
2031 }
2032
2033
2034 /**************************************************************************
2035  *              IsSelectionOwner (X11DRV.@)
2036  *
2037  * Returns: TRUE if the selection is owned by this process, FALSE otherwise
2038  */
2039 static BOOL X11DRV_CLIPBOARD_IsSelectionOwner(void)
2040 {
2041     return selectionAcquired;
2042 }
2043
2044
2045 /**************************************************************************
2046  *                X11DRV Clipboard Exports
2047  **************************************************************************/
2048
2049
2050 /**************************************************************************
2051  *              RegisterClipboardFormat (X11DRV.@)
2052  *
2053  * Registers a custom X clipboard format
2054  * Returns: Format id or 0 on failure
2055  */
2056 INT X11DRV_RegisterClipboardFormat(LPCWSTR FormatName)
2057 {
2058     LPWINE_CLIPFORMAT lpFormat;
2059
2060     if (FormatName == NULL) return 0;
2061     if (!(lpFormat = register_format( FormatName, 0 ))) return 0;
2062     return lpFormat->wFormatID;
2063 }
2064
2065
2066 /**************************************************************************
2067  *              X11DRV_GetClipboardFormatName
2068  */
2069 INT X11DRV_GetClipboardFormatName(UINT wFormat, LPWSTR retStr, INT maxlen)
2070 {
2071     LPWINE_CLIPFORMAT lpFormat;
2072
2073     TRACE("(%04X, %p, %d) !\n", wFormat, retStr, maxlen);
2074
2075     if (wFormat < 0xc000)
2076     {
2077         SetLastError(ERROR_INVALID_PARAMETER);
2078         return 0;
2079     }
2080
2081     lpFormat = X11DRV_CLIPBOARD_LookupFormat(wFormat);
2082
2083     if (!lpFormat || (lpFormat->wFlags & CF_FLAG_BUILTINFMT))
2084     {
2085         TRACE("Unknown format 0x%08x!\n", wFormat);
2086         SetLastError(ERROR_INVALID_HANDLE);
2087         return 0;
2088     }
2089
2090     lstrcpynW(retStr, lpFormat->Name, maxlen);
2091
2092     return strlenW(retStr);
2093 }
2094
2095
2096 /**************************************************************************
2097  *              AcquireClipboard (X11DRV.@)
2098  */
2099 void X11DRV_AcquireClipboard(HWND hWndClipWindow)
2100 {
2101     Display *display = thread_display();
2102
2103     /*
2104      * Acquire X selection if we don't already own it.
2105      * Note that we only acquire the selection if it hasn't been already
2106      * acquired by us, and ignore the fact that another X window may be
2107      * asserting ownership. The reason for this is we need *any* top level
2108      * X window to hold selection ownership. The actual clipboard data requests
2109      * are made via GetClipboardData from EVENT_SelectionRequest and this
2110      * ensures that the real HWND owner services the request.
2111      * If the owning X window gets destroyed the selection ownership is
2112      * re-cycled to another top level X window in X11DRV_CLIPBOARD_ResetOwner.
2113      *
2114      */
2115     if (!(selectionAcquired == (S_PRIMARY | S_CLIPBOARD)))
2116     {
2117         Window owner;
2118
2119         if (!hWndClipWindow)
2120             hWndClipWindow = GetActiveWindow();
2121
2122         owner = X11DRV_get_whole_window(GetAncestor(hWndClipWindow, GA_ROOT));
2123
2124         wine_tsx11_lock();
2125         /* Grab PRIMARY selection if not owned */
2126         if (usePrimary && !(selectionAcquired & S_PRIMARY))
2127             XSetSelectionOwner(display, XA_PRIMARY, owner, CurrentTime);
2128
2129         /* Grab CLIPBOARD selection if not owned */
2130         if (!(selectionAcquired & S_CLIPBOARD))
2131             XSetSelectionOwner(display, x11drv_atom(CLIPBOARD), owner, CurrentTime);
2132
2133         if (usePrimary && XGetSelectionOwner(display,XA_PRIMARY) == owner)
2134             selectionAcquired |= S_PRIMARY;
2135
2136         if (XGetSelectionOwner(display,x11drv_atom(CLIPBOARD)) == owner)
2137             selectionAcquired |= S_CLIPBOARD;
2138         wine_tsx11_unlock();
2139
2140         if (selectionAcquired)
2141         {
2142             selectionWindow = owner;
2143             TRACE("Grabbed X selection, owner=(%08x)\n", (unsigned) owner);
2144         }
2145     }
2146     else
2147     {
2148         WARN("Received request to acquire selection but process is already owner=(%08x)\n", (unsigned) selectionWindow);
2149
2150         selectionAcquired  = S_NOSELECTION;
2151
2152         wine_tsx11_lock();
2153         if (XGetSelectionOwner(display,XA_PRIMARY) == selectionWindow)
2154             selectionAcquired |= S_PRIMARY;
2155
2156         if (XGetSelectionOwner(display,x11drv_atom(CLIPBOARD)) == selectionWindow)
2157             selectionAcquired |= S_CLIPBOARD;
2158         wine_tsx11_unlock();
2159
2160         if (!(selectionAcquired == (S_PRIMARY | S_CLIPBOARD)))
2161         {
2162             WARN("Lost selection but process didn't process SelectClear\n");
2163             selectionWindow = None;
2164         }
2165     }
2166 }
2167
2168
2169 /**************************************************************************
2170  *      X11DRV_EmptyClipboard
2171  *
2172  * Empty cached clipboard data. 
2173  */
2174 void X11DRV_EmptyClipboard(BOOL keepunowned)
2175 {
2176     if (ClipData)
2177     {
2178         LPWINE_CLIPDATA lpData, lpStart;
2179         LPWINE_CLIPDATA lpNext = ClipData;
2180
2181         TRACE(" called with %d entries in cache.\n", ClipDataCount);
2182
2183         do
2184         {
2185             lpStart = ClipData;
2186             lpData = lpNext;
2187             lpNext = lpData->NextData;
2188
2189             if (!keepunowned || !(lpData->wFlags & CF_FLAG_UNOWNED))
2190             {
2191             lpData->PrevData->NextData = lpData->NextData;
2192             lpData->NextData->PrevData = lpData->PrevData;
2193
2194                 if (lpData == ClipData)
2195                     ClipData = lpNext != lpData ? lpNext : NULL;
2196
2197             X11DRV_CLIPBOARD_FreeData(lpData);
2198             HeapFree(GetProcessHeap(), 0, lpData);
2199
2200                 ClipDataCount--;
2201             }
2202         } while (lpNext != lpStart);
2203     }
2204
2205     TRACE(" %d entries remaining in cache.\n", ClipDataCount);
2206 }
2207
2208
2209
2210 /**************************************************************************
2211  *              X11DRV_SetClipboardData
2212  */
2213 BOOL X11DRV_SetClipboardData(UINT wFormat, HANDLE16 hData16, HANDLE hData32, BOOL owner)
2214 {
2215     DWORD flags = 0;
2216     BOOL bResult = TRUE;
2217
2218     /* If it's not owned, data can only be set if the format data is not already owned
2219        and its rendering is not delayed */
2220     if (!owner)
2221 {
2222         CLIPBOARDINFO cbinfo;
2223         LPWINE_CLIPDATA lpRender;
2224
2225         X11DRV_CLIPBOARD_UpdateCache(&cbinfo);
2226
2227         if ((!hData16 && !hData32) ||
2228             ((lpRender = X11DRV_CLIPBOARD_LookupData(wFormat)) &&
2229             !(lpRender->wFlags & CF_FLAG_UNOWNED)))
2230             bResult = FALSE;
2231         else
2232             flags = CF_FLAG_UNOWNED;
2233     }
2234
2235     bResult &= X11DRV_CLIPBOARD_InsertClipboardData(wFormat, hData16, hData32, flags);
2236
2237     return bResult;
2238 }
2239
2240
2241 /**************************************************************************
2242  *              CountClipboardFormats
2243  */
2244 INT X11DRV_CountClipboardFormats(void)
2245 {
2246     CLIPBOARDINFO cbinfo;
2247
2248     X11DRV_CLIPBOARD_UpdateCache(&cbinfo);
2249
2250     TRACE(" count=%d\n", ClipDataCount);
2251
2252     return ClipDataCount;
2253 }
2254
2255
2256 /**************************************************************************
2257  *              X11DRV_EnumClipboardFormats
2258  */
2259 UINT X11DRV_EnumClipboardFormats(UINT wFormat)
2260 {
2261     CLIPBOARDINFO cbinfo;
2262     UINT wNextFormat = 0;
2263
2264     TRACE("(%04X)\n", wFormat);
2265
2266     X11DRV_CLIPBOARD_UpdateCache(&cbinfo);
2267
2268     if (!wFormat)
2269     {
2270         if (ClipData)
2271             wNextFormat = ClipData->wFormatID;
2272     }
2273     else
2274     {
2275         LPWINE_CLIPDATA lpData = X11DRV_CLIPBOARD_LookupData(wFormat);
2276
2277         if (lpData && lpData->NextData != ClipData)
2278             wNextFormat = lpData->NextData->wFormatID;
2279     }
2280
2281     return wNextFormat;
2282 }
2283
2284
2285 /**************************************************************************
2286  *              X11DRV_IsClipboardFormatAvailable
2287  */
2288 BOOL X11DRV_IsClipboardFormatAvailable(UINT wFormat)
2289 {
2290     BOOL bRet = FALSE;
2291     CLIPBOARDINFO cbinfo;
2292
2293     TRACE("(%04X)\n", wFormat);
2294
2295     X11DRV_CLIPBOARD_UpdateCache(&cbinfo);
2296
2297     if (wFormat != 0 && X11DRV_CLIPBOARD_LookupData(wFormat))
2298         bRet = TRUE;
2299
2300     TRACE("(%04X)- ret(%d)\n", wFormat, bRet);
2301
2302     return bRet;
2303 }
2304
2305
2306 /**************************************************************************
2307  *              GetClipboardData (USER.142)
2308  */
2309 BOOL X11DRV_GetClipboardData(UINT wFormat, HANDLE16* phData16, HANDLE* phData32)
2310 {
2311     CLIPBOARDINFO cbinfo;
2312     LPWINE_CLIPDATA lpRender;
2313
2314     TRACE("(%04X)\n", wFormat);
2315
2316     X11DRV_CLIPBOARD_UpdateCache(&cbinfo);
2317
2318     if ((lpRender = X11DRV_CLIPBOARD_LookupData(wFormat)))
2319     {
2320         if ( !lpRender->hData32 )
2321             X11DRV_CLIPBOARD_RenderFormat(lpRender);
2322
2323         /* Convert between 32 -> 16 bit data, if necessary */
2324         if (lpRender->hData32 && !lpRender->hData16)
2325         {
2326             int size;
2327
2328             if (lpRender->wFormatID == CF_METAFILEPICT)
2329                 size = sizeof(METAFILEPICT16);
2330             else
2331                 size = GlobalSize(lpRender->hData32);
2332
2333             lpRender->hData16 = GlobalAlloc16(GMEM_ZEROINIT, size);
2334
2335             if (!lpRender->hData16)
2336                 ERR("(%04X) -- not enough memory in 16b heap\n", wFormat);
2337             else
2338             {
2339                 if (lpRender->wFormatID == CF_METAFILEPICT)
2340                 {
2341                     FIXME("\timplement function CopyMetaFilePict32to16\n");
2342                     FIXME("\tin the appropriate file.\n");
2343   #ifdef SOMEONE_IMPLEMENTED_ME
2344                     CopyMetaFilePict32to16(GlobalLock16(lpRender->hData16),
2345                         GlobalLock(lpRender->hData32));
2346   #endif
2347                 }
2348                 else
2349                 {
2350                     memcpy(GlobalLock16(lpRender->hData16),
2351                         GlobalLock(lpRender->hData32), size);
2352                 }
2353
2354                 GlobalUnlock16(lpRender->hData16);
2355                 GlobalUnlock(lpRender->hData32);
2356             }
2357         }
2358
2359         /* Convert between 32 -> 16 bit data, if necessary */
2360         if (lpRender->hData16 && !lpRender->hData32)
2361         {
2362             int size;
2363
2364             if (lpRender->wFormatID == CF_METAFILEPICT)
2365                 size = sizeof(METAFILEPICT16);
2366             else
2367                 size = GlobalSize(lpRender->hData32);
2368
2369             lpRender->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | 
2370                 GMEM_DDESHARE, size);
2371
2372             if (lpRender->wFormatID == CF_METAFILEPICT)
2373             {
2374                 FIXME("\timplement function CopyMetaFilePict16to32\n");
2375                 FIXME("\tin the appropriate file.\n");
2376 #ifdef SOMEONE_IMPLEMENTED_ME
2377                 CopyMetaFilePict16to32(GlobalLock16(lpRender->hData32),
2378                     GlobalLock(lpRender->hData16));
2379 #endif
2380             }
2381             else
2382             {
2383                 memcpy(GlobalLock(lpRender->hData32),
2384                     GlobalLock16(lpRender->hData16), size);
2385             }
2386
2387             GlobalUnlock(lpRender->hData32);
2388             GlobalUnlock16(lpRender->hData16);
2389         }
2390
2391         if (phData16)
2392             *phData16 = lpRender->hData16;
2393
2394         if (phData32)
2395             *phData32 = lpRender->hData32;
2396
2397         TRACE(" returning hData16(%04x) hData32(%04x) (type %d)\n", 
2398             lpRender->hData16, (unsigned int) lpRender->hData32, lpRender->wFormatID);
2399
2400         return lpRender->hData16 || lpRender->hData32;
2401     }
2402
2403     return 0;
2404 }
2405
2406
2407 /**************************************************************************
2408  *              ResetSelectionOwner (X11DRV.@)
2409  *
2410  * Called from DestroyWindow() to prevent X selection from being lost when
2411  * a top level window is destroyed, by switching ownership to another top
2412  * level window.
2413  * Any top level window can own the selection. See X11DRV_CLIPBOARD_Acquire
2414  * for a more detailed description of this.
2415  */
2416 void X11DRV_ResetSelectionOwner(HWND hwnd, BOOL bFooBar)
2417 {
2418     Display *display = thread_display();
2419     HWND hWndClipOwner = 0;
2420     HWND tmp;
2421     Window XWnd = X11DRV_get_whole_window(hwnd);
2422     BOOL bLostSelection = FALSE;
2423     Window selectionPrevWindow;
2424
2425     /* There is nothing to do if we don't own the selection,
2426      * or if the X window which currently owns the selection is different
2427      * from the one passed in.
2428      */
2429     if (!selectionAcquired || XWnd != selectionWindow
2430          || selectionWindow == None )
2431        return;
2432
2433     if ((bFooBar && XWnd) || (!bFooBar && !XWnd))
2434        return;
2435
2436     hWndClipOwner = GetClipboardOwner();
2437
2438     TRACE("clipboard owner = %p, selection window = %08x\n",
2439           hWndClipOwner, (unsigned)selectionWindow);
2440
2441     /* now try to salvage current selection from being destroyed by X */
2442     TRACE("checking %08x\n", (unsigned) XWnd);
2443
2444     selectionPrevWindow = selectionWindow;
2445     selectionWindow = None;
2446
2447     if (!(tmp = GetWindow(hwnd, GW_HWNDNEXT)))
2448         tmp = GetWindow(hwnd, GW_HWNDFIRST);
2449
2450     if (tmp && tmp != hwnd) 
2451         selectionWindow = X11DRV_get_whole_window(tmp);
2452
2453     if (selectionWindow != None)
2454     {
2455         /* We must pretend that we don't own the selection while making the switch
2456          * since a SelectionClear event will be sent to the last owner.
2457          * If there is no owner X11DRV_CLIPBOARD_ReleaseSelection will do nothing.
2458          */
2459         int saveSelectionState = selectionAcquired;
2460         selectionAcquired = S_NOSELECTION;
2461
2462         TRACE("\tswitching selection from %08x to %08x\n",
2463                     (unsigned)selectionPrevWindow, (unsigned)selectionWindow);
2464
2465         wine_tsx11_lock();
2466
2467         /* Assume ownership for the PRIMARY and CLIPBOARD selection */
2468         if (saveSelectionState & S_PRIMARY)
2469             XSetSelectionOwner(display, XA_PRIMARY, selectionWindow, CurrentTime);
2470
2471         XSetSelectionOwner(display, x11drv_atom(CLIPBOARD), selectionWindow, CurrentTime);
2472
2473         /* Restore the selection masks */
2474         selectionAcquired = saveSelectionState;
2475
2476         /* Lose the selection if something went wrong */
2477         if (((saveSelectionState & S_PRIMARY) &&
2478            (XGetSelectionOwner(display, XA_PRIMARY) != selectionWindow)) || 
2479            (XGetSelectionOwner(display, x11drv_atom(CLIPBOARD)) != selectionWindow))
2480         {
2481             bLostSelection = TRUE;
2482         }
2483         wine_tsx11_unlock();
2484     }
2485     else
2486     {
2487         bLostSelection = TRUE;
2488     }
2489
2490     if (bLostSelection)
2491     {
2492         TRACE("Lost the selection!\n");
2493
2494         X11DRV_CLIPBOARD_ReleaseOwnership();
2495         selectionAcquired = S_NOSELECTION;
2496         selectionWindow = 0;
2497     }
2498 }
2499
2500
2501 /**************************************************************************
2502  *                      X11DRV_CLIPBOARD_SynthesizeData
2503  */
2504 static BOOL X11DRV_CLIPBOARD_SynthesizeData(UINT wFormatID)
2505 {
2506     BOOL bsyn = TRUE;
2507     LPWINE_CLIPDATA lpSource = NULL;
2508
2509     TRACE(" %d\n", wFormatID);
2510
2511     /* Don't need to synthesize if it already exists */
2512     if (X11DRV_CLIPBOARD_LookupData(wFormatID))
2513         return TRUE;
2514
2515     if (wFormatID == CF_UNICODETEXT || wFormatID == CF_TEXT || wFormatID == CF_OEMTEXT)
2516     {
2517         bsyn = ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_UNICODETEXT)) &&
2518             ~lpSource->wFlags & CF_FLAG_SYNTHESIZED) ||
2519             ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_TEXT)) &&
2520             ~lpSource->wFlags & CF_FLAG_SYNTHESIZED) ||
2521             ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_OEMTEXT)) &&
2522             ~lpSource->wFlags & CF_FLAG_SYNTHESIZED);
2523     }
2524     else if (wFormatID == CF_ENHMETAFILE)
2525     {
2526         bsyn = (lpSource = X11DRV_CLIPBOARD_LookupData(CF_METAFILEPICT)) &&
2527             ~lpSource->wFlags & CF_FLAG_SYNTHESIZED;
2528     }
2529     else if (wFormatID == CF_METAFILEPICT)
2530     {
2531         bsyn = (lpSource = X11DRV_CLIPBOARD_LookupData(CF_METAFILEPICT)) &&
2532             ~lpSource->wFlags & CF_FLAG_SYNTHESIZED;
2533     }
2534     else if (wFormatID == CF_DIB)
2535     {
2536         bsyn = (lpSource = X11DRV_CLIPBOARD_LookupData(CF_BITMAP)) &&
2537             ~lpSource->wFlags & CF_FLAG_SYNTHESIZED;
2538     }
2539     else if (wFormatID == CF_BITMAP)
2540     {
2541         bsyn = (lpSource = X11DRV_CLIPBOARD_LookupData(CF_DIB)) &&
2542             ~lpSource->wFlags & CF_FLAG_SYNTHESIZED;
2543     }
2544
2545     if (bsyn)
2546         X11DRV_CLIPBOARD_InsertClipboardData(wFormatID, 0, 0, CF_FLAG_SYNTHESIZED);
2547
2548     return bsyn;
2549 }
2550
2551
2552
2553 /**************************************************************************
2554  *              X11DRV_EndClipboardUpdate
2555  * TODO:
2556  *  Add locale if it hasn't already been added
2557  */
2558 void X11DRV_EndClipboardUpdate(void)
2559 {
2560     INT count = ClipDataCount;
2561
2562     /* Do Unicode <-> Text <-> OEM mapping */
2563     X11DRV_CLIPBOARD_SynthesizeData(CF_UNICODETEXT);
2564     X11DRV_CLIPBOARD_SynthesizeData(CF_TEXT);
2565     X11DRV_CLIPBOARD_SynthesizeData(CF_OEMTEXT);
2566
2567     /* Enhmetafile <-> MetafilePict mapping */
2568     X11DRV_CLIPBOARD_SynthesizeData(CF_ENHMETAFILE);
2569     X11DRV_CLIPBOARD_SynthesizeData(CF_METAFILEPICT);
2570
2571     /* DIB <-> Bitmap mapping */
2572     X11DRV_CLIPBOARD_SynthesizeData(CF_DIB);
2573     X11DRV_CLIPBOARD_SynthesizeData(CF_BITMAP);
2574
2575     TRACE("%d formats added to cached data\n", ClipDataCount - count);
2576 }