- Implement interprocess clipboard communication.
[wine] / windows / clipboard.c
1 /*
2  * WIN32 clipboard implementation
3  *
4  * Copyright 1994 Martin Ayotte
5  *           1996 Alex Korobka
6  *           1999 Noel Borthwick
7  *
8  * NOTES:
9  *    This file contains the implementation for the WIN32 Clipboard API
10  * and Wine's internal clipboard cache.
11  * The actual contents of the clipboard are held in the clipboard cache.
12  * The internal implementation talks to a "clipboard driver" to fill or
13  * expose the cache to the native device. (Currently only the X11 and
14  * TTY clipboard  driver are available)
15  *
16  * TODO: 
17  *
18  */
19
20 #include <stdlib.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <fcntl.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include "winuser.h"
27 #include "wine/winuser16.h"
28 #include "wine/winbase16.h"
29 #include "heap.h"
30 #include "message.h"
31 #include "task.h"
32 #include "queue.h"
33 #include "clipboard.h"
34 #include "xmalloc.h"
35 #include "debugtools.h"
36
37 DEFAULT_DEBUG_CHANNEL(clipboard)
38
39 #define  CF_REGFORMATBASE       0xC000
40
41 /**************************************************************************
42  *        Clipboard context global variables
43  */
44
45 CLIPBOARD_DRIVER *CLIPBOARD_Driver = NULL;
46
47 static HANDLE hClipLock   = 0;
48 static BOOL bCBHasChanged  = FALSE;
49
50 HWND hWndClipWindow = 0;          /* window that last opened clipboard */
51 HWND hWndClipOwner  = 0;          /* current clipboard owner */
52 HANDLE16 hTaskClipOwner = 0;      /* clipboard owner's task  */
53 static HWND hWndViewer     = 0;   /* start of viewers chain */
54
55 static WORD LastRegFormat = CF_REGFORMATBASE;
56
57 /* Clipboard cache initial data.
58  * WARNING: This data ordering is dependendent on the WINE_CLIPFORMAT structure
59  * declared in clipboard.h
60  */
61 WINE_CLIPFORMAT ClipFormats[16]  = {
62     { CF_TEXT, 1, 0, "Text",  (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, NULL, &ClipFormats[1]},
63     { CF_BITMAP, 1, 0, "Bitmap", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[0], &ClipFormats[2]},
64     { CF_METAFILEPICT, 1, 0, "MetaFile Picture", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[1], &ClipFormats[3]},
65     { CF_SYLK, 1, 0, "Sylk", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[2], &ClipFormats[4]},
66     { CF_DIF, 1, 0, "DIF", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[3], &ClipFormats[5]},
67     { CF_TIFF, 1, 0, "TIFF", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[4], &ClipFormats[6]},
68     { CF_OEMTEXT, 1, 0, "OEM Text", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[5], &ClipFormats[7]},
69     { CF_DIB, 1, 0, "DIB", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[6], &ClipFormats[8]},
70     { CF_PALETTE, 1, 0, "Palette", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[7], &ClipFormats[9]},
71     { CF_PENDATA, 1, 0, "PenData", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[8], &ClipFormats[10]},
72     { CF_RIFF, 1, 0, "RIFF", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[9], &ClipFormats[11]},
73     { CF_WAVE, 1, 0, "Wave", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[10], &ClipFormats[12]},
74     { CF_OWNERDISPLAY, 1, 0, "Owner Display", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[11], &ClipFormats[13]},
75     { CF_DSPTEXT, 1, 0, "DSPText", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[12], &ClipFormats[14]},
76     { CF_DSPMETAFILEPICT, 1, 0, "DSPMetaFile Picture", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[13], &ClipFormats[15]},
77     { CF_DSPBITMAP, 1, 0, "DSPBitmap", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[14], NULL}
78     };
79
80
81 /**************************************************************************
82  *                Internal Clipboard implementation methods
83  **************************************************************************/
84
85
86 /**************************************************************************
87  *                      CLIPBOARD_LookupFormat
88  */
89 static LPWINE_CLIPFORMAT __lookup_format( LPWINE_CLIPFORMAT lpFormat, WORD wID )
90 {
91     while(TRUE)
92     {
93         if (lpFormat == NULL ||
94             lpFormat->wFormatID == wID) break;
95         lpFormat = lpFormat->NextFormat;
96     }
97     return lpFormat;
98 }
99
100 LPWINE_CLIPFORMAT CLIPBOARD_LookupFormat( WORD wID )
101 {
102   return __lookup_format( ClipFormats, wID );
103 }
104
105 /**************************************************************************
106  *                      CLIPBOARD_IsLocked
107  *  Check if the clipboard cache is available to the caller
108  */
109 BOOL CLIPBOARD_IsLocked()
110 {
111   BOOL bIsLocked = TRUE;
112   HANDLE16 hTaskCur = GetCurrentTask();
113
114   /*
115    * The clipboard is available:
116    * 1. if the caller's task has opened the clipboard,
117    * or
118    * 2. if the caller is the clipboard owners task, AND is responding to a
119    *    WM_RENDERFORMAT message.
120    */
121   if ( hClipLock == hTaskCur )
122       bIsLocked = FALSE;
123       
124   else if ( hTaskCur == hTaskClipOwner )
125   {
126       /* Check if we're currently executing inside a window procedure
127        * called in response to a WM_RENDERFORMAT message. A WM_RENDERFORMAT
128        * handler is not permitted to open the clipboard since it has been opened
129        * by another client. However the handler must have access to the
130        * clipboard in order to update data in response to this message.
131        */
132       MESSAGEQUEUE *queue = QUEUE_Lock( GetFastQueue16() );
133       
134       if ( queue
135            && queue->smWaiting
136            && queue->smWaiting->msg == WM_RENDERFORMAT
137            && queue->smWaiting->hSrcQueue
138          )
139         bIsLocked = FALSE;
140         
141       QUEUE_Unlock( queue );
142   }
143
144   return bIsLocked;
145 }
146
147 /**************************************************************************
148  *                      CLIPBOARD_ReleaseOwner
149  *   Gives up ownership of the clipboard
150  */
151 void CLIPBOARD_ReleaseOwner()
152 {
153    hWndClipOwner = 0;
154    hTaskClipOwner = 0;
155 }
156
157 /**************************************************************************
158  *                      CLIPBOARD_GlobalFreeProc
159  *
160  * This is a callback mechanism to allow HGLOBAL data to be released in
161  * the context of the process which allocated it. We post a WM_TIMER message
162  * to the owner window(in CLIPBOARD_DeleteRecord) and destroy the data(in idEvent)
163  * in this WndProc, which is invoked when the apps message loop calls DispatchMessage.
164  * This technique is discussed in Matt Pietrek's "Under the Hood".
165  * An article describing the same may be found in MSDN by searching for WM_TIMER.
166  * Note that this mechanism will probably stop working when WINE supports
167  * address space separation. When "queue events" are implemented in Wine we
168  * should switch to using that mechanism, since it is more robust and does not
169  * require a procedure address to be passed. See the SetWinEventHook API for
170  * more info on this.
171  */
172 VOID CALLBACK CLIPBOARD_GlobalFreeProc( HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime )
173 {
174     /* idEvent is the HGLOBAL to be deleted */
175     GlobalFree( (HGLOBAL)idEvent );
176 }
177
178 /**************************************************************************
179  *                      CLIPBOARD_DeleteRecord
180  */
181 void CLIPBOARD_DeleteRecord(LPWINE_CLIPFORMAT lpFormat, BOOL bChange)
182 {
183     if( (lpFormat->wFormatID >= CF_GDIOBJFIRST &&
184          lpFormat->wFormatID <= CF_GDIOBJLAST) || lpFormat->wFormatID == CF_BITMAP )
185     {
186       if (lpFormat->hData32)
187         DeleteObject(lpFormat->hData32);
188       if (lpFormat->hData16)
189         DeleteObject16(lpFormat->hData16);
190     }
191     else if( lpFormat->wFormatID == CF_METAFILEPICT )
192     {
193       if (lpFormat->hData32)
194       {
195         DeleteMetaFile( ((METAFILEPICT *)GlobalLock( lpFormat->hData32 ))->hMF );
196         PostMessageA(hWndClipOwner, WM_TIMER,
197                      (WPARAM)lpFormat->hData32, (LPARAM)CLIPBOARD_GlobalFreeProc);
198         if (lpFormat->hDataSrc32)
199         {
200           /* Release lpFormat->hData32 in the context of the process which created it.
201            * See CLIPBOARD_GlobalFreeProc for more details about this technique.
202            * GlobalFree(lpFormat->hDataSrc32);
203            */
204           PostMessageA(hWndClipOwner, WM_TIMER,
205                        (WPARAM)lpFormat->hDataSrc32, (LPARAM)CLIPBOARD_GlobalFreeProc);
206         }
207           
208         if (lpFormat->hData16)
209           /* HMETAFILE16 and HMETAFILE32 are apparently the same thing, 
210              and a shallow copy is enough to share a METAFILEPICT
211              structure between 16bit and 32bit clipboards.  The MetaFile
212              should of course only be deleted once. */
213           GlobalFree16(lpFormat->hData16);
214       }
215       if (lpFormat->hData16)
216       {
217         DeleteMetaFile16( ((METAFILEPICT16 *)GlobalLock16( lpFormat->hData16 ))->hMF );
218         GlobalFree16(lpFormat->hData16);
219       }
220     }
221     else 
222     {
223       if (lpFormat->hData32)
224       {
225         /* Release lpFormat->hData32 in the context of the process which created it.
226          * See CLIPBOARD_GlobalFreeProc for more details about this technique.
227          * GlobalFree( lpFormat->hData32 );
228          */
229         PostMessageA(hWndClipOwner, WM_TIMER,
230                      (WPARAM)lpFormat->hData32, (LPARAM)CLIPBOARD_GlobalFreeProc);
231       }
232       if (lpFormat->hDataSrc32)
233       {
234         /* Release lpFormat->hData32 in the context of the process which created it.
235          * See CLIPBOARD_GlobalFreeProc for more details about this technique.
236          * GlobalFree(lpFormat->hDataSrc32);
237          */
238         PostMessageA(hWndClipOwner, WM_TIMER,
239                      (WPARAM)lpFormat->hDataSrc32, (LPARAM)CLIPBOARD_GlobalFreeProc);
240       }
241       if (lpFormat->hData16)
242         GlobalFree16(lpFormat->hData16);
243     }
244
245     lpFormat->wDataPresent = 0; 
246     lpFormat->hData16 = 0;
247     lpFormat->hData32 = 0;
248     lpFormat->hDataSrc32 = 0;
249     lpFormat->drvData = 0;
250
251     if( bChange ) bCBHasChanged = TRUE;
252 }
253
254 /**************************************************************************
255  *                      CLIPBOARD_EmptyCache
256  */
257 void CLIPBOARD_EmptyCache( BOOL bChange )
258 {
259     LPWINE_CLIPFORMAT lpFormat = ClipFormats; 
260
261     while(lpFormat)
262     {
263         if ( lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32 )
264              CLIPBOARD_DeleteRecord( lpFormat, bChange );
265
266         lpFormat = lpFormat->NextFormat;
267     }
268 }
269
270 /**************************************************************************
271  *                      CLIPBOARD_IsPresent
272  */
273 BOOL CLIPBOARD_IsPresent(WORD wFormat)
274 {
275     /* special case */
276
277     if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
278         return ClipFormats[CF_TEXT-1].wDataPresent ||
279                ClipFormats[CF_OEMTEXT-1].wDataPresent;
280     else
281     {
282         LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
283         if( lpFormat ) return (lpFormat->wDataPresent);
284     }
285     return FALSE;
286 }
287
288 /**************************************************************************
289  *                      CLIPBOARD_IsCacheRendered
290  *  Checks if any data needs to be rendered to the clipboard cache
291  *  RETURNS:
292  *    TRUE  - All clipboard data is available in the cache
293  *    FALSE - Some data is marked for delayed render and needs rendering
294  */
295 BOOL CLIPBOARD_IsCacheRendered()
296 {
297     LPWINE_CLIPFORMAT lpFormat = ClipFormats;
298     
299     /* check if all formats were rendered */
300     while(lpFormat)
301     {
302         if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
303             return FALSE;
304         
305         lpFormat = lpFormat->NextFormat;
306     }
307     
308     return TRUE;
309 }
310
311
312 /**************************************************************************
313  *                      CLIPBOARD_IsMemoryObject
314  *  Tests if the clipboard format specifies a memory object
315  */
316 BOOL CLIPBOARD_IsMemoryObject( WORD wFormat )
317 {
318     switch(wFormat)
319     {
320         case CF_BITMAP:
321         case CF_METAFILEPICT:
322         case CF_DSPTEXT:
323         case CF_ENHMETAFILE:
324         case CF_HDROP:
325         case CF_PALETTE:
326         case CF_PENDATA:
327             return FALSE;
328         default:
329             return TRUE;
330      }
331 }
332
333 /***********************************************************************
334  * CLIPBOARD_GlobalDupMem( HGLOBAL )
335  * Helper method to duplicate an HGLOBAL chunk of memory into shared memory
336  */
337 HGLOBAL CLIPBOARD_GlobalDupMem( HGLOBAL hGlobalSrc )
338 {
339     HGLOBAL hGlobalDest;
340     PVOID pGlobalSrc, pGlobalDest;
341     DWORD cBytes;
342     
343     if ( !hGlobalSrc )
344       return 0;
345
346     cBytes = GlobalSize(hGlobalSrc);
347     if ( 0 == cBytes )
348       return 0;
349
350     /* Turn on the DDESHARE and _MOVEABLE flags explicitly */
351     hGlobalDest = GlobalAlloc( GlobalFlags(hGlobalSrc) | GMEM_DDESHARE | GMEM_MOVEABLE,
352                                cBytes );
353     if ( !hGlobalDest )
354       return 0;
355     
356     pGlobalSrc = GlobalLock(hGlobalSrc);
357     pGlobalDest = GlobalLock(hGlobalDest);
358     if ( !pGlobalSrc || !pGlobalDest )
359       return 0;
360
361     memcpy(pGlobalDest, pGlobalSrc, cBytes);
362         
363     GlobalUnlock(hGlobalSrc);
364     GlobalUnlock(hGlobalDest);
365
366     return hGlobalDest;
367 }
368
369 /**************************************************************************
370  *                      CLIPBOARD_GetFormatName
371  *  Gets the format name associated with an ID
372  */
373 char * CLIPBOARD_GetFormatName(UINT wFormat)
374 {
375     LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
376     return (lpFormat) ? lpFormat->Name : NULL;
377 }
378
379
380 /**************************************************************************
381  *                      CLIPBOARD_RenderFormat
382  */
383 static BOOL CLIPBOARD_RenderFormat(LPWINE_CLIPFORMAT lpFormat)
384 {
385   /*
386    * If WINE is not the selection owner, and the format is available
387    * we must ask the the driver to render the data to the clipboard cache.
388    */
389   if ( !CLIPBOARD_Driver->pIsSelectionOwner() 
390        && CLIPBOARD_Driver->pIsFormatAvailable( lpFormat->wFormatID ) )
391   {
392     if ( !CLIPBOARD_Driver->pGetData( lpFormat->wFormatID ) )
393       return FALSE;
394   }
395   /*
396    * If Wine owns the clipboard, and the data is marked for delayed render,
397    * render it now.
398    */
399   else if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
400   {
401     if( IsWindow(hWndClipOwner) )
402     {
403       /* Send a WM_RENDERFORMAT message to notify the owner to render the
404        * data requested into the clipboard.
405        */
406       TRACE("Sending WM_RENDERFORMAT message\n");
407       SendMessage16(hWndClipOwner,WM_RENDERFORMAT,
408                     (WPARAM16)lpFormat->wFormatID,0L);
409     }
410     else
411     {
412       WARN("\thWndClipOwner (%04x) is lost!\n", 
413            hWndClipOwner);
414       CLIPBOARD_ReleaseOwner();
415       lpFormat->wDataPresent = 0;
416       return FALSE;
417     }
418   }
419
420   return (lpFormat->hData16 || lpFormat->hData32) ? TRUE : FALSE;
421 }
422
423
424 /**************************************************************************
425  *                      CLIPBOARD_RenderText
426  *
427  * Renders text to the clipboard buffer converting between UNIX and DOS formats.
428  *
429  * RETURNS: pointer to the WINE_CLIPFORMAT if successful, NULL otherwise
430  *
431  * FIXME: Should be a pair of driver functions that convert between OEM text and Windows.
432  *
433  */
434 static LPWINE_CLIPFORMAT CLIPBOARD_RenderText( UINT wFormat )
435 {
436     LPWINE_CLIPFORMAT lpSource = ClipFormats; 
437     LPWINE_CLIPFORMAT lpTarget;
438     
439     /* Asked for CF_TEXT and not available - always attempt to convert from CF_OEM_TEXT */
440     if( wFormat == CF_TEXT && !ClipFormats[CF_TEXT-1].wDataPresent )
441     {
442         /* Convert OEMTEXT -> TEXT */
443         lpSource = &ClipFormats[CF_OEMTEXT-1];
444         lpTarget = &ClipFormats[CF_TEXT-1];
445
446         TRACE("\tOEMTEXT -> TEXT\n");
447     }
448     /* Asked for CF_OEM_TEXT, and CF_TEXT available */
449     else if( wFormat == CF_OEMTEXT && !ClipFormats[CF_OEMTEXT-1].wDataPresent
450                                    &&  ClipFormats[CF_TEXT-1].wDataPresent )
451     {
452         /* Convert TEXT -> OEMTEXT */
453         lpSource = &ClipFormats[CF_TEXT-1];
454         lpTarget = &ClipFormats[CF_OEMTEXT-1];
455         
456         TRACE("\tTEXT -> OEMTEXT\n");
457     }
458     /* Text format requested is available - no conversion necessary */
459     else
460     {
461         lpSource = __lookup_format( ClipFormats, wFormat );
462         lpTarget = lpSource;
463     }
464
465     /* First render the source text format */
466     if ( !lpSource || !CLIPBOARD_RenderFormat(lpSource) ) return NULL;
467
468     /* Convert to the desired target text format, if necessary */
469     if( lpTarget != lpSource && !lpTarget->hData16 && !lpTarget->hData32 )
470     {
471         UINT16 size;
472         LPCSTR lpstrS; 
473         LPSTR  lpstrT;
474     
475         if (lpSource->hData32)
476         {
477           size = GlobalSize( lpSource->hData32 );
478           lpstrS = (LPSTR)GlobalLock(lpSource->hData32);
479         }
480         else
481         {
482           size = GlobalSize16( lpSource->hData16 );
483           lpstrS = (LPSTR)GlobalLock16(lpSource->hData16);
484         }
485     
486         if( !lpstrS ) return NULL;
487         TRACE("\tconverting from '%s' to '%s', %i chars\n",
488                                           lpSource->Name, lpTarget->Name, size);
489     
490         lpTarget->hData32 = GlobalAlloc(GMEM_ZEROINIT, size);
491         lpstrT = (LPSTR)GlobalLock(lpTarget->hData32);
492     
493         if( lpstrT )
494         {
495             if( lpSource->wFormatID == CF_TEXT )
496                 CharToOemBuffA(lpstrS, lpstrT, size);
497             else
498                 OemToCharBuffA(lpstrS, lpstrT, size);
499             TRACE("\tgot %s\n", lpstrT);
500             GlobalUnlock(lpTarget->hData32);
501         }
502         else
503             lpTarget->hData32 = 0;
504
505         /* Unlock source */
506         if (lpSource->hData32)
507           GlobalUnlock(lpSource->hData32);
508         else
509           GlobalUnlock16(lpSource->hData16);
510     }
511
512     return (lpTarget->hData16 || lpTarget->hData32) ? lpTarget : NULL;
513 }
514
515 /**************************************************************************
516  *                WIN32 Clipboard implementation 
517  **************************************************************************/
518
519 /**************************************************************************
520  *            OpenClipboard16   (USER.137)
521  */
522 BOOL16 WINAPI OpenClipboard16( HWND16 hWnd )
523 {
524     return OpenClipboard( hWnd );
525 }
526
527
528 /**************************************************************************
529  *            OpenClipboard32   (USER32.407)
530  *
531  * Note: Netscape uses NULL hWnd to open the clipboard.
532  */
533 BOOL WINAPI OpenClipboard( HWND hWnd )
534 {
535     BOOL bRet;
536
537     TRACE("(%04x)...\n", hWnd);
538
539     if (!hClipLock)
540     {
541         hClipLock = GetCurrentTask();
542
543         /* Save current user of the clipboard */
544         hWndClipWindow = hWnd;
545         bCBHasChanged = FALSE;
546         bRet = TRUE;
547     }
548     else bRet = FALSE;
549
550     TRACE("   returning %i\n", bRet);
551     return bRet;
552 }
553
554
555 /**************************************************************************
556  *            CloseClipboard16   (USER.138)
557  */
558 BOOL16 WINAPI CloseClipboard16(void)
559 {
560     return CloseClipboard();
561 }
562
563
564 /**************************************************************************
565  *            CloseClipboard32   (USER32.54)
566  */
567 BOOL WINAPI CloseClipboard(void)
568 {
569     TRACE("()\n");
570
571     if (hClipLock == GetCurrentTask())
572     {
573         hWndClipWindow = 0;
574
575         if (bCBHasChanged && hWndViewer) 
576             SendMessage16(hWndViewer, WM_DRAWCLIPBOARD, 0, 0L);
577         hClipLock = 0;
578     }
579     return TRUE;
580 }
581
582
583 /**************************************************************************
584  *            EmptyClipboard16   (USER.139)
585  */
586 BOOL16 WINAPI EmptyClipboard16(void)
587 {
588     return EmptyClipboard();
589 }
590
591
592 /**************************************************************************
593  *            EmptyClipboard32   (USER32.169)
594  *  Empties and acquires ownership of the clipboard
595  */
596 BOOL WINAPI EmptyClipboard(void)
597 {
598     TRACE("()\n");
599
600     if (hClipLock != GetCurrentTask())
601     {
602         WARN("Clipboard not opened by calling task!");
603         return FALSE;
604     }
605     
606     /* destroy private objects */
607
608     if (hWndClipOwner)
609         SendMessage16(hWndClipOwner, WM_DESTROYCLIPBOARD, 0, 0L);
610
611     /* empty the cache */
612     CLIPBOARD_EmptyCache(TRUE);
613
614     /* Assign ownership of the clipboard to the current client */
615     hWndClipOwner = hWndClipWindow;
616
617     /* Save the current task */
618     hTaskClipOwner = GetCurrentTask();
619     
620     /* Tell the driver to acquire the selection */
621     CLIPBOARD_Driver->pAcquire();
622
623     return TRUE;
624 }
625
626
627 /**************************************************************************
628  *            GetClipboardOwner16   (USER.140)
629  *  FIXME: Can't return the owner if the clipbard is owned by an external app
630  */
631 HWND16 WINAPI GetClipboardOwner16(void)
632 {
633     TRACE("()\n");
634     return hWndClipOwner;
635 }
636
637
638 /**************************************************************************
639  *            GetClipboardOwner32   (USER32.225)
640  *  FIXME: Can't return the owner if the clipbard is owned by an external app
641  */
642 HWND WINAPI GetClipboardOwner(void)
643 {
644     TRACE("()\n");
645     return hWndClipOwner;
646 }
647
648
649 /**************************************************************************
650  *            SetClipboardData16   (USER.141)
651  */
652 HANDLE16 WINAPI SetClipboardData16( UINT16 wFormat, HANDLE16 hData )
653 {
654     LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
655
656     TRACE("(%04X, %04x) !\n", wFormat, hData);
657
658     /* NOTE: If the hData is zero and current owner doesn't match
659      * the window that opened the clipboard then this application
660      * is screwed because WM_RENDERFORMAT will go to the owner.
661      * (to become the owner it must call EmptyClipboard() before
662      *  adding new data).
663      */
664
665     if( CLIPBOARD_IsLocked() || !lpFormat ||
666         (!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) )
667     {
668         WARN("Invalid hData or clipboard not opened by calling task!");
669         return 0;
670     }
671
672     /* Pass on the request to the driver */
673     CLIPBOARD_Driver->pSetData(wFormat);
674
675     if ( lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32 ) 
676     {
677         CLIPBOARD_DeleteRecord(lpFormat, TRUE);
678
679         /* delete existing CF_TEXT/CF_OEMTEXT aliases */
680
681         if( wFormat == CF_TEXT 
682             && ( ClipFormats[CF_OEMTEXT-1].hData16 
683                  ||  ClipFormats[CF_OEMTEXT-1].hData32 )
684             && !ClipFormats[CF_OEMTEXT-1].wDataPresent )
685             CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
686         if( wFormat == CF_OEMTEXT 
687             && ( ClipFormats[CF_OEMTEXT-1].hData16 
688                  ||  ClipFormats[CF_OEMTEXT-1].hData32 )
689             && !ClipFormats[CF_TEXT-1].wDataPresent )
690             CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
691     }
692
693     bCBHasChanged = TRUE;
694     lpFormat->wDataPresent = 1;
695     lpFormat->hData16 = hData;          /* 0 is legal, see WM_RENDERFORMAT */
696     lpFormat->hData32 = 0;
697
698     return lpFormat->hData16;
699 }
700
701
702 /**************************************************************************
703  *            SetClipboardData   (USER32.470)
704  */
705 HANDLE WINAPI SetClipboardData( UINT wFormat, HANDLE hData )
706 {
707     LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
708
709     TRACE("(%08X, %08x) !\n", wFormat, hData);
710
711     /* NOTE: If the hData is zero and current owner doesn't match
712      * the window that opened the clipboard then this application
713      * is screwed because WM_RENDERFORMAT will go to the owner.
714      * (to become the owner it must call EmptyClipboard() before
715      *  adding new data).
716      */
717
718     if( CLIPBOARD_IsLocked() || !lpFormat ||
719         (!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) )
720     {
721         WARN("Invalid hData or clipboard not opened by calling task!");
722         return 0;
723     }
724
725     /* Tell the driver to acquire the selection */
726     CLIPBOARD_Driver->pAcquire();
727
728     if ( lpFormat->wDataPresent &&
729          (lpFormat->hData16 || lpFormat->hData32) )
730     {
731         CLIPBOARD_DeleteRecord(lpFormat, TRUE);
732
733         /* delete existing CF_TEXT/CF_OEMTEXT aliases */
734
735         if( wFormat == CF_TEXT 
736             && ( ClipFormats[CF_OEMTEXT-1].hData16 
737                  ||  ClipFormats[CF_OEMTEXT-1].hData32 )
738             && !ClipFormats[CF_OEMTEXT-1].wDataPresent )
739             CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
740         if( wFormat == CF_OEMTEXT 
741             && ( ClipFormats[CF_OEMTEXT-1].hData16 
742                  ||  ClipFormats[CF_OEMTEXT-1].hData32 )
743             && !ClipFormats[CF_TEXT-1].wDataPresent )
744             CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
745     }
746
747     bCBHasChanged = TRUE;
748     lpFormat->wDataPresent = 1;
749     lpFormat->hDataSrc32 = hData;  /* Save the source handle */
750
751     /*
752      * Make a shared duplicate if the memory is not shared
753      * TODO: What should be done for non-memory objects
754      */
755     if ( CLIPBOARD_IsMemoryObject(wFormat) && hData && !(GlobalFlags(hData) & GMEM_DDESHARE) )
756         lpFormat->hData32 = CLIPBOARD_GlobalDupMem( hData );
757     else
758         lpFormat->hData32 = hData;          /* 0 is legal, see WM_RENDERFORMAT */
759     
760     lpFormat->hData16 = 0;
761
762     return lpFormat->hData32;   /* Should we return lpFormat->hDataSrc32 */
763 }
764
765
766 /**************************************************************************
767  *             GetClipboardData16   (USER.142)
768  */
769 HANDLE16 WINAPI GetClipboardData16( UINT16 wFormat )
770 {
771     LPWINE_CLIPFORMAT lpRender = ClipFormats; 
772
773     TRACE("(%04X)\n", wFormat);
774
775     if (CLIPBOARD_IsLocked())
776     {
777         WARN("Clipboard not opened by calling task!");
778         return 0;
779     }
780
781     if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
782     {
783         lpRender = CLIPBOARD_RenderText(wFormat);
784         if ( !lpRender ) return 0;
785     }
786     else
787     {
788         lpRender = __lookup_format( ClipFormats, wFormat );
789         if( !lpRender || !CLIPBOARD_RenderFormat(lpRender) ) return 0;
790     }
791    
792     /* Convert between 32 -> 16 bit data, if necessary */
793     if( lpRender->hData32 && !lpRender->hData16 )
794     {
795       int size;
796       if( lpRender->wFormatID == CF_METAFILEPICT )
797         size = sizeof( METAFILEPICT16 );
798       else
799         size = GlobalSize(lpRender->hData32);
800       lpRender->hData16 = GlobalAlloc16(GMEM_ZEROINIT, size);
801       if( !lpRender->hData16 )
802         ERR("(%04X) -- not enough memory in 16b heap\n", wFormat);
803       else
804       {
805       if( lpRender->wFormatID == CF_METAFILEPICT )
806       {
807         FIXME("\timplement function CopyMetaFilePict32to16\n");
808         FIXME("\tin the appropriate file.\n");
809 #ifdef SOMEONE_IMPLEMENTED_ME
810         CopyMetaFilePict32to16( GlobalLock16(lpRender->hData16), 
811                                 GlobalLock(lpRender->hData32) );
812 #endif
813       }
814       else
815       {
816         memcpy( GlobalLock16(lpRender->hData16), 
817                 GlobalLock(lpRender->hData32), 
818                 size );
819       }
820         GlobalUnlock16(lpRender->hData16);
821         GlobalUnlock(lpRender->hData32);
822       }
823     }
824
825     TRACE("\treturning %04x (type %i)\n", 
826                               lpRender->hData16, lpRender->wFormatID);
827     return lpRender->hData16;
828 }
829
830
831 /**************************************************************************
832  *             GetClipboardData32   (USER32.222)
833  */
834 HANDLE WINAPI GetClipboardData( UINT wFormat )
835 {
836     LPWINE_CLIPFORMAT lpRender = ClipFormats; 
837
838     TRACE("(%08X)\n", wFormat);
839
840     if (CLIPBOARD_IsLocked())
841     {
842         WARN("Clipboard not opened by calling task!");
843         return 0;
844     }
845
846     if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
847     {
848         lpRender = CLIPBOARD_RenderText(wFormat);
849         if ( !lpRender ) return 0;
850     }
851     else
852     {
853         lpRender = __lookup_format( ClipFormats, wFormat );
854         if( !lpRender || !CLIPBOARD_RenderFormat(lpRender) ) return 0;
855     }
856    
857     /* Convert between 16 -> 32 bit data, if necessary */
858     if( lpRender->hData16 && !lpRender->hData32 )
859     {
860       int size;
861       if( lpRender->wFormatID == CF_METAFILEPICT )
862         size = sizeof( METAFILEPICT );
863       else
864         size = GlobalSize16(lpRender->hData16);
865       lpRender->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE,
866                                       size);
867       if( lpRender->wFormatID == CF_METAFILEPICT )
868       {
869         FIXME("\timplement function CopyMetaFilePict16to32\n");
870         FIXME("\tin the appropriate file.\n");
871 #ifdef SOMEONE_IMPLEMENTED_ME
872         CopyMetaFilePict16to32( GlobalLock16(lpRender->hData32), 
873                                 GlobalLock(lpRender->hData16) );
874 #endif
875       }
876       else
877       {
878         memcpy( GlobalLock(lpRender->hData32), 
879                 GlobalLock16(lpRender->hData16), 
880                 size );
881       }
882       GlobalUnlock(lpRender->hData32);
883       GlobalUnlock16(lpRender->hData16);
884     }
885
886     TRACE("\treturning %04x (type %i)\n", 
887                               lpRender->hData32, lpRender->wFormatID);
888     return lpRender->hData32;
889 }
890
891
892 /**************************************************************************
893  *           CountClipboardFormats16   (USER.143)
894  */
895 INT16 WINAPI CountClipboardFormats16(void)
896 {
897     return CountClipboardFormats();
898 }
899
900
901 /**************************************************************************
902  *           CountClipboardFormats32   (USER32.63)
903  */
904 INT WINAPI CountClipboardFormats(void)
905 {
906     INT FormatCount = 0;
907     LPWINE_CLIPFORMAT lpFormat = ClipFormats; 
908
909     TRACE("()\n");
910
911     while(TRUE) 
912     {
913         if (lpFormat == NULL) break;
914
915         if( lpFormat->wFormatID != CF_TEXT ) /* Don't count CF_TEXT */
916         {
917           /*
918            * The format is available if either:
919            * 1. The data is already in the cache.
920            * 2. The selection is not owned by us(WINE) and the data is
921            *    available to the clipboard driver.
922            */
923           if ( lpFormat->wDataPresent ||
924                ( !CLIPBOARD_Driver->pIsSelectionOwner()
925                  && CLIPBOARD_Driver->pIsFormatAvailable( lpFormat->wFormatID ) ) )
926           {
927               TRACE("\tdata found for format %i(%s)\n",
928                     lpFormat->wFormatID, CLIPBOARD_GetFormatName(lpFormat->wFormatID));
929               FormatCount++;
930           }
931         }
932
933         lpFormat = lpFormat->NextFormat;
934     }
935
936     /* these two are equivalent, adjust the total */
937
938     FormatCount += abs(ClipFormats[CF_TEXT-1].wDataPresent -
939                        ClipFormats[CF_OEMTEXT-1].wDataPresent);
940
941     TRACE("\ttotal %d\n", FormatCount);
942     return FormatCount;
943 }
944
945
946 /**************************************************************************
947  *            EnumClipboardFormats16   (USER.144)
948  */
949 UINT16 WINAPI EnumClipboardFormats16( UINT16 wFormat )
950 {
951     return EnumClipboardFormats( wFormat );
952 }
953
954
955 /**************************************************************************
956  *            EnumClipboardFormats32   (USER32.179)
957  */
958 UINT WINAPI EnumClipboardFormats( UINT wFormat )
959 {
960     LPWINE_CLIPFORMAT lpFormat = ClipFormats;
961     BOOL bFormatPresent;
962
963     TRACE("(%04X)\n", wFormat);
964
965     if (CLIPBOARD_IsLocked())
966     {
967         WARN("Clipboard not opened by calling task!");
968         return 0;
969     }
970
971     if (wFormat == 0) /* start from the beginning */
972         lpFormat = ClipFormats;
973     else
974     {
975         /* walk up to the specified format record */
976
977         if( !(lpFormat = __lookup_format( lpFormat, wFormat )) ) 
978             return 0;
979         lpFormat = lpFormat->NextFormat; /* right */
980     }
981
982     while(TRUE) 
983     {
984         if (lpFormat == NULL) return 0;
985
986         /* Synthesize CF_TEXT from CF_OEMTEXT and vice versa */
987         bFormatPresent = (lpFormat->wDataPresent ||
988            (lpFormat->wFormatID == CF_OEMTEXT && ClipFormats[CF_TEXT-1].wDataPresent) ||
989            (lpFormat->wFormatID == CF_TEXT && ClipFormats[CF_OEMTEXT-1].wDataPresent) );
990
991         /* Query the driver if not yet in the cache */
992         if (!bFormatPresent && !CLIPBOARD_Driver->pIsSelectionOwner())
993         {
994             bFormatPresent =
995                CLIPBOARD_Driver->pIsFormatAvailable( (lpFormat->wFormatID == CF_TEXT) ?
996                                                       CF_OEMTEXT : lpFormat->wFormatID );
997         }
998
999         if (bFormatPresent)
1000             break;
1001
1002         lpFormat = lpFormat->NextFormat;
1003     }
1004
1005     return lpFormat->wFormatID;
1006 }
1007
1008
1009 /**************************************************************************
1010  *            RegisterClipboardFormat16  (USER.145)
1011  */
1012 UINT16 WINAPI RegisterClipboardFormat16( LPCSTR FormatName )
1013 {
1014     LPWINE_CLIPFORMAT lpNewFormat; 
1015     LPWINE_CLIPFORMAT lpFormat = ClipFormats; 
1016
1017     if (FormatName == NULL) return 0;
1018
1019     TRACE("('%s') !\n", FormatName);
1020
1021     /* walk format chain to see if it's already registered */
1022
1023     while(TRUE) 
1024     {
1025         if ( !strcmp(lpFormat->Name,FormatName) )
1026         {
1027              lpFormat->wRefCount++;
1028              return lpFormat->wFormatID;
1029         }
1030  
1031         if ( lpFormat->NextFormat == NULL ) break;
1032
1033         lpFormat = lpFormat->NextFormat;
1034     }
1035
1036     /* allocate storage for new format entry */
1037
1038     lpNewFormat = (LPWINE_CLIPFORMAT)xmalloc(sizeof(WINE_CLIPFORMAT));
1039     lpFormat->NextFormat = lpNewFormat;
1040     lpNewFormat->wFormatID = LastRegFormat;
1041     lpNewFormat->wRefCount = 1;
1042
1043     lpNewFormat->Name = (LPSTR)xmalloc(strlen(FormatName) + 1);
1044     strcpy(lpNewFormat->Name, FormatName);
1045
1046     lpNewFormat->wDataPresent = 0;
1047     lpNewFormat->hData16 = 0;
1048     lpNewFormat->hDataSrc32 = 0;
1049     lpNewFormat->hData32 = 0;
1050     lpNewFormat->drvData = 0;
1051     lpNewFormat->PrevFormat = lpFormat;
1052     lpNewFormat->NextFormat = NULL;
1053
1054     /* Pass on the registration request to the driver */
1055     CLIPBOARD_Driver->pRegisterFormat( FormatName );
1056     
1057     return LastRegFormat++;
1058 }
1059
1060
1061 /**************************************************************************
1062  *            RegisterClipboardFormat32A   (USER32.431)
1063  */
1064 UINT WINAPI RegisterClipboardFormatA( LPCSTR formatName )
1065 {
1066     return RegisterClipboardFormat16( formatName );
1067 }
1068
1069
1070 /**************************************************************************
1071  *            RegisterClipboardFormat32W   (USER32.432)
1072  */
1073 UINT WINAPI RegisterClipboardFormatW( LPCWSTR formatName )
1074 {
1075     LPSTR aFormat = HEAP_strdupWtoA( GetProcessHeap(), 0, formatName );
1076     UINT ret = RegisterClipboardFormatA( aFormat );
1077     HeapFree( GetProcessHeap(), 0, aFormat );
1078     return ret;
1079 }
1080
1081
1082 /**************************************************************************
1083  *            GetClipboardFormatName16   (USER.146)
1084  */
1085 INT16 WINAPI GetClipboardFormatName16( UINT16 wFormat, LPSTR retStr, INT16 maxlen )
1086 {
1087     return GetClipboardFormatNameA( wFormat, retStr, maxlen );
1088 }
1089
1090
1091 /**************************************************************************
1092  *            GetClipboardFormatName32A   (USER32.223)
1093  */
1094 INT WINAPI GetClipboardFormatNameA( UINT wFormat, LPSTR retStr, INT maxlen )
1095 {
1096     LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
1097
1098     TRACE("(%04X, %p, %d) !\n", wFormat, retStr, maxlen);
1099
1100     if (lpFormat == NULL || lpFormat->Name == NULL || 
1101         lpFormat->wFormatID < CF_REGFORMATBASE) return 0;
1102
1103     TRACE("Name='%s' !\n", lpFormat->Name);
1104
1105     lstrcpynA( retStr, lpFormat->Name, maxlen );
1106     return strlen(retStr);
1107 }
1108
1109
1110 /**************************************************************************
1111  *            GetClipboardFormatName32W   (USER32.224)
1112  */
1113 INT WINAPI GetClipboardFormatNameW( UINT wFormat, LPWSTR retStr, INT maxlen )
1114 {
1115     LPSTR p = HEAP_xalloc( GetProcessHeap(), 0, maxlen );
1116     INT ret = GetClipboardFormatNameA( wFormat, p, maxlen );
1117     lstrcpynAtoW( retStr, p, maxlen );
1118     HeapFree( GetProcessHeap(), 0, p );
1119     return ret;
1120 }
1121
1122
1123 /**************************************************************************
1124  *            SetClipboardViewer16   (USER.147)
1125  */
1126 HWND16 WINAPI SetClipboardViewer16( HWND16 hWnd )
1127 {
1128     TRACE("(%04x)\n", hWnd);
1129     return SetClipboardViewer( hWnd );
1130 }
1131
1132
1133 /**************************************************************************
1134  *            SetClipboardViewer32   (USER32.471)
1135  */
1136 HWND WINAPI SetClipboardViewer( HWND hWnd )
1137 {
1138     HWND hwndPrev = hWndViewer;
1139
1140     TRACE("(%04x): returning %04x\n", hWnd, hwndPrev);
1141
1142     hWndViewer = hWnd;
1143     return hwndPrev;
1144 }
1145
1146
1147 /**************************************************************************
1148  *           GetClipboardViewer16   (USER.148)
1149  */
1150 HWND16 WINAPI GetClipboardViewer16(void)
1151 {
1152     TRACE("()\n");
1153     return hWndViewer;
1154 }
1155
1156
1157 /**************************************************************************
1158  *           GetClipboardViewer32   (USER32.226)
1159  */
1160 HWND WINAPI GetClipboardViewer(void)
1161 {
1162     TRACE("()\n");
1163     return hWndViewer;
1164 }
1165
1166
1167 /**************************************************************************
1168  *           ChangeClipboardChain16   (USER.149)
1169  */
1170 BOOL16 WINAPI ChangeClipboardChain16(HWND16 hWnd, HWND16 hWndNext)
1171 {
1172     return ChangeClipboardChain(hWnd, hWndNext);
1173 }
1174
1175
1176 /**************************************************************************
1177  *           ChangeClipboardChain32   (USER32.22)
1178  */
1179 BOOL WINAPI ChangeClipboardChain(HWND hWnd, HWND hWndNext)
1180 {
1181     BOOL bRet = 0;
1182
1183     FIXME("(0x%04x, 0x%04x): stub?\n", hWnd, hWndNext);
1184
1185     if( hWndViewer )
1186         bRet = !SendMessage16( hWndViewer, WM_CHANGECBCHAIN,
1187                              (WPARAM16)hWnd, (LPARAM)hWndNext);   
1188     else
1189         WARN("hWndViewer is lost\n");
1190
1191     if( hWnd == hWndViewer ) hWndViewer = hWndNext;
1192
1193     return bRet;
1194 }
1195
1196
1197 /**************************************************************************
1198  *           IsClipboardFormatAvailable16   (USER.193)
1199  */
1200 BOOL16 WINAPI IsClipboardFormatAvailable16( UINT16 wFormat )
1201 {
1202     return IsClipboardFormatAvailable( wFormat );
1203 }
1204
1205
1206 /**************************************************************************
1207  *           IsClipboardFormatAvailable32   (USER32.340)
1208  */
1209 BOOL WINAPI IsClipboardFormatAvailable( UINT wFormat )
1210 {
1211     BOOL bRet;
1212
1213     if (wFormat == 0)  /* Reject this case quickly */
1214         bRet = FALSE;
1215
1216     /* If WINE is not the clipboard selection owner ask the clipboard driver */
1217     else if ( !CLIPBOARD_Driver->pIsSelectionOwner() )
1218         bRet = CLIPBOARD_Driver->pIsFormatAvailable( (wFormat == CF_TEXT) ?
1219                                                      CF_OEMTEXT : wFormat );
1220     /* Check if the format is in the local cache */
1221     else 
1222         bRet = CLIPBOARD_IsPresent(wFormat);
1223
1224     TRACE("(%04X)- ret(%d)\n", wFormat, bRet);
1225     return bRet;
1226 }
1227
1228
1229 /**************************************************************************
1230  *             GetOpenClipboardWindow16   (USER.248)
1231  *  FIXME: This wont work if an external app owns the selection
1232  */
1233 HWND16 WINAPI GetOpenClipboardWindow16(void)
1234 {
1235     TRACE("()\n");
1236     return hWndClipWindow;
1237 }
1238
1239
1240 /**************************************************************************
1241  *             GetOpenClipboardWindow32   (USER32.277)
1242  *  FIXME: This wont work if an external app owns the selection
1243  */
1244 HWND WINAPI GetOpenClipboardWindow(void)
1245 {
1246     TRACE("()\n");
1247     return hWndClipWindow;
1248 }
1249
1250
1251 /**************************************************************************
1252  *             GetPriorityClipboardFormat16   (USER.402)
1253  */
1254 INT16 WINAPI GetPriorityClipboardFormat16( UINT16 *lpPriorityList, INT16 nCount)
1255 {
1256     FIXME("(%p,%d): stub\n", lpPriorityList, nCount );
1257     return 0;
1258 }
1259
1260
1261 /**************************************************************************
1262  *             GetPriorityClipboardFormat32   (USER32.279)
1263  */
1264 INT WINAPI GetPriorityClipboardFormat( UINT *lpPriorityList, INT nCount )
1265 {
1266     int Counter;
1267     TRACE("()\n");
1268
1269     if(CountClipboardFormats() == 0) 
1270     { 
1271         return 0;
1272     }
1273
1274     for(Counter = 0; Counter <= nCount; Counter++)
1275     {
1276         if(IsClipboardFormatAvailable(*(lpPriorityList+sizeof(INT)*Counter)))
1277             return *(lpPriorityList+sizeof(INT)*Counter);
1278     }
1279
1280     return -1;
1281 }
1282