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