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