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