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