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