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