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