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