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