Do not invalidate the window before the first paint job.
[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 /**************************************************************************
61  *        Clipboard context global variables
62  */
63
64 static HANDLE hClipLock   = 0;
65 static BOOL bCBHasChanged  = FALSE;
66
67 static HWND hWndClipWindow;        /* window that last opened clipboard */
68 static HWND hWndClipOwner;         /* current clipboard owner */
69 static HANDLE16 hTaskClipOwner;    /* clipboard owner's task  */
70 static HWND hWndViewer;            /* start of viewers chain */
71
72 /* Clipboard cache initial data.
73  * WARNING: This data ordering is dependent on the WINE_CLIPFORMAT structure
74  * declared in clipboard.h
75  */
76 WINE_CLIPFORMAT ClipFormats[]  = {
77     { CF_TEXT, 1, 0, "Text",  0, 0, 0, 0, NULL, &ClipFormats[1]},
78     { CF_BITMAP, 1, 0, "Bitmap", 0, 0, 0, 0, &ClipFormats[0], &ClipFormats[2]},
79     { CF_METAFILEPICT, 1, 0, "MetaFile Picture", 0, 0, 0, 0, &ClipFormats[1], &ClipFormats[3]},
80     { CF_SYLK, 1, 0, "Sylk", 0, 0, 0, 0, &ClipFormats[2], &ClipFormats[4]},
81     { CF_DIF, 1, 0, "DIF", 0, 0, 0, 0, &ClipFormats[3], &ClipFormats[5]},
82     { CF_TIFF, 1, 0, "TIFF", 0, 0, 0, 0, &ClipFormats[4], &ClipFormats[6]},
83     { CF_OEMTEXT, 1, 0, "OEM Text", 0, 0, 0, 0, &ClipFormats[5], &ClipFormats[7]},
84     { CF_DIB, 1, 0, "DIB", 0, 0, 0, 0, &ClipFormats[6], &ClipFormats[8]},
85     { CF_PALETTE, 1, 0, "Palette", 0, 0, 0, 0, &ClipFormats[7], &ClipFormats[9]},
86     { CF_PENDATA, 1, 0, "PenData", 0, 0, 0, 0, &ClipFormats[8], &ClipFormats[10]},
87     { CF_RIFF, 1, 0, "RIFF", 0, 0, 0, 0, &ClipFormats[9], &ClipFormats[11]},
88     { CF_WAVE, 1, 0, "Wave", 0, 0, 0, 0, &ClipFormats[10], &ClipFormats[12]},
89     { CF_UNICODETEXT, 1, 0, "Unicode Text", 0, 0, 0, 0, &ClipFormats[11], &ClipFormats[13]},
90     { CF_OWNERDISPLAY, 1, 0, "Owner Display", 0, 0, 0, 0, &ClipFormats[12], &ClipFormats[14]},
91     { CF_DSPTEXT, 1, 0, "DSPText", 0, 0, 0, 0, &ClipFormats[13], &ClipFormats[15]},
92     { CF_DSPMETAFILEPICT, 1, 0, "DSPMetaFile Picture", 0, 0, 0, 0, &ClipFormats[14], &ClipFormats[16]},
93     { CF_DSPBITMAP, 1, 0, "DSPBitmap", 0, 0, 0, 0, &ClipFormats[15], &ClipFormats[17]},
94     { CF_HDROP, 1, 0, "HDROP", 0, 0, 0, 0, &ClipFormats[16], &ClipFormats[18]},
95     { CF_ENHMETAFILE, 1, 0, "Enhmetafile", 0, 0, 0, 0, &ClipFormats[17], NULL}
96 };
97
98
99 /**************************************************************************
100  *                Internal Clipboard implementation methods
101  **************************************************************************/
102
103
104 /**************************************************************************
105  *                      CLIPBOARD_LookupFormat
106  */
107 static LPWINE_CLIPFORMAT __lookup_format( LPWINE_CLIPFORMAT lpFormat, WORD wID )
108 {
109     while(TRUE)
110     {
111         if (lpFormat == NULL ||
112             lpFormat->wFormatID == wID) break;
113         lpFormat = lpFormat->NextFormat;
114     }
115     return lpFormat;
116 }
117
118 LPWINE_CLIPFORMAT CLIPBOARD_LookupFormat( WORD wID )
119 {
120   return __lookup_format( ClipFormats, wID );
121 }
122
123 /**************************************************************************
124  *                      CLIPBOARD_IsLocked
125  *  Check if the clipboard cache is available to the caller
126  */
127 BOOL CLIPBOARD_IsLocked()
128 {
129   BOOL bIsLocked = TRUE;
130   HANDLE16 hTaskCur = GetCurrentTask();
131
132   /*
133    * The clipboard is available:
134    * 1. if the caller's task has opened the clipboard,
135    * or
136    * 2. if the caller is the clipboard owners task, AND is responding to a
137    *    WM_RENDERFORMAT message.
138    */
139   if ( hClipLock == hTaskCur )
140       bIsLocked = FALSE;
141
142   else if ( hTaskCur == hTaskClipOwner )
143   {
144       /* Check if we're currently executing inside a window procedure
145        * called in response to a WM_RENDERFORMAT message. A WM_RENDERFORMAT
146        * handler is not permitted to open the clipboard since it has been opened
147        * by another client. However the handler must have access to the
148        * clipboard in order to update data in response to this message.
149        */
150 #if 0
151       MESSAGEQUEUE *queue = QUEUE_Current();
152
153       if ( queue
154            && queue->smWaiting
155            && queue->smWaiting->msg == WM_RENDERFORMAT
156            && queue->smWaiting->hSrcQueue
157          )
158         bIsLocked = FALSE;
159 #else
160       /* FIXME: queue check no longer possible */
161       bIsLocked = FALSE;
162 #endif
163   }
164
165   return bIsLocked;
166 }
167
168 /**************************************************************************
169  *                      CLIPBOARD_ReleaseOwner
170  *   Gives up ownership of the clipboard
171  */
172 void CLIPBOARD_ReleaseOwner()
173 {
174    hWndClipOwner = 0;
175    hTaskClipOwner = 0;
176 }
177
178 /**************************************************************************
179  *                      CLIPBOARD_GlobalFreeProc
180  *
181  * This is a callback mechanism to allow HGLOBAL data to be released in
182  * the context of the process which allocated it. We post a WM_TIMER message
183  * to the owner window(in CLIPBOARD_DeleteRecord) and destroy the data(in idEvent)
184  * in this WndProc, which is invoked when the apps message loop calls DispatchMessage.
185  * This technique is discussed in Matt Pietrek's "Under the Hood".
186  * An article describing the same may be found in MSDN by searching for WM_TIMER.
187  * Note that this mechanism will probably stop working when WINE supports
188  * address space separation. When "queue events" are implemented in Wine we
189  * should switch to using that mechanism, since it is more robust and does not
190  * require a procedure address to be passed. See the SetWinEventHook API for
191  * more info on this.
192  */
193 VOID CALLBACK CLIPBOARD_GlobalFreeProc( HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime )
194 {
195     /* idEvent is the HGLOBAL to be deleted */
196     GlobalFree( (HGLOBAL)idEvent );
197 }
198
199 /**************************************************************************
200  *                      CLIPBOARD_DeleteRecord
201  */
202 void CLIPBOARD_DeleteRecord(LPWINE_CLIPFORMAT lpFormat, BOOL bChange)
203 {
204     if( (lpFormat->wFormatID >= CF_GDIOBJFIRST &&
205          lpFormat->wFormatID <= CF_GDIOBJLAST) || lpFormat->wFormatID == CF_BITMAP
206             || lpFormat->wFormatID == CF_PALETTE)
207     {
208       if (lpFormat->hData32)
209         DeleteObject(lpFormat->hData32);
210       if (lpFormat->hData16)
211         DeleteObject(lpFormat->hData16);
212     }
213     else if( lpFormat->wFormatID == CF_METAFILEPICT )
214     {
215       if (lpFormat->hData32)
216       {
217         DeleteMetaFile( ((METAFILEPICT *)GlobalLock( lpFormat->hData32 ))->hMF );
218         PostMessageA(hWndClipOwner, WM_TIMER,
219                      (WPARAM)lpFormat->hData32, (LPARAM)CLIPBOARD_GlobalFreeProc);
220         if (lpFormat->hDataSrc32)
221         {
222           /* Release lpFormat->hData32 in the context of the process which created it.
223            * See CLIPBOARD_GlobalFreeProc for more details about this technique.
224            * GlobalFree(lpFormat->hDataSrc32);
225            */
226           PostMessageA(hWndClipOwner, WM_TIMER,
227                        (WPARAM)lpFormat->hDataSrc32, (LPARAM)CLIPBOARD_GlobalFreeProc);
228         }
229
230         if (lpFormat->hData16)
231           /* HMETAFILE16 and HMETAFILE32 are apparently the same thing,
232              and a shallow copy is enough to share a METAFILEPICT
233              structure between 16bit and 32bit clipboards.  The MetaFile
234              should of course only be deleted once. */
235           GlobalFree16(lpFormat->hData16);
236       }
237       if (lpFormat->hData16)
238       {
239         DeleteMetaFile16( ((METAFILEPICT16 *)GlobalLock16( lpFormat->hData16 ))->hMF );
240         GlobalFree16(lpFormat->hData16);
241       }
242     }
243     else
244     {
245       if (lpFormat->hData32)
246       {
247         /* Release lpFormat->hData32 in the context of the process which created it.
248          * See CLIPBOARD_GlobalFreeProc for more details about this technique.
249          * GlobalFree( lpFormat->hData32 );
250          */
251         PostMessageA(hWndClipOwner, WM_TIMER,
252                      (WPARAM)lpFormat->hData32, (LPARAM)CLIPBOARD_GlobalFreeProc);
253       }
254       if (lpFormat->hDataSrc32)
255       {
256         /* Release lpFormat->hData32 in the context of the process which created it.
257          * See CLIPBOARD_GlobalFreeProc for more details about this technique.
258          * GlobalFree(lpFormat->hDataSrc32);
259          */
260         PostMessageA(hWndClipOwner, WM_TIMER,
261                      (WPARAM)lpFormat->hDataSrc32, (LPARAM)CLIPBOARD_GlobalFreeProc);
262       }
263       if (lpFormat->hData16)
264         GlobalFree16(lpFormat->hData16);
265     }
266
267     lpFormat->wDataPresent = 0;
268     lpFormat->hData16 = 0;
269     lpFormat->hData32 = 0;
270     lpFormat->hDataSrc32 = 0;
271     lpFormat->drvData = 0;
272
273     if( bChange ) bCBHasChanged = TRUE;
274 }
275
276 /**************************************************************************
277  *                      CLIPBOARD_EmptyCache
278  */
279 void CLIPBOARD_EmptyCache( BOOL bChange )
280 {
281     LPWINE_CLIPFORMAT lpFormat = ClipFormats;
282
283     while(lpFormat)
284     {
285         if ( lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32 )
286              CLIPBOARD_DeleteRecord( lpFormat, bChange );
287
288         lpFormat = lpFormat->NextFormat;
289     }
290 }
291
292 /**************************************************************************
293  *                      CLIPBOARD_IsPresent
294  */
295 BOOL CLIPBOARD_IsPresent(WORD wFormat)
296 {
297     /* special case */
298
299     if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT || wFormat == CF_UNICODETEXT )
300         return ClipFormats[CF_TEXT-1].wDataPresent ||
301                ClipFormats[CF_OEMTEXT-1].wDataPresent ||
302                ClipFormats[CF_UNICODETEXT-1].wDataPresent;
303     else
304     {
305         LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
306         if( lpFormat ) return (lpFormat->wDataPresent);
307     }
308     return FALSE;
309 }
310
311 /**************************************************************************
312  *                      CLIPBOARD_IsCacheRendered
313  *  Checks if any data needs to be rendered to the clipboard cache
314  *  RETURNS:
315  *    TRUE  - All clipboard data is available in the cache
316  *    FALSE - Some data is marked for delayed render and needs rendering
317  */
318 BOOL CLIPBOARD_IsCacheRendered()
319 {
320     LPWINE_CLIPFORMAT lpFormat = ClipFormats;
321
322     /* check if all formats were rendered */
323     while(lpFormat)
324     {
325         if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
326             return FALSE;
327
328         lpFormat = lpFormat->NextFormat;
329     }
330
331     return TRUE;
332 }
333
334
335 /**************************************************************************
336  *                      CLIPBOARD_IsMemoryObject
337  *  Tests if the clipboard format specifies a memory object
338  */
339 BOOL CLIPBOARD_IsMemoryObject( WORD wFormat )
340 {
341     switch(wFormat)
342     {
343         case CF_BITMAP:
344         case CF_METAFILEPICT:
345         case CF_DSPTEXT:
346         case CF_ENHMETAFILE:
347         case CF_HDROP:
348         case CF_PALETTE:
349         case CF_PENDATA:
350             return FALSE;
351         default:
352             return TRUE;
353      }
354 }
355
356 /***********************************************************************
357  * CLIPBOARD_GlobalDupMem( HGLOBAL )
358  * Helper method to duplicate an HGLOBAL chunk of memory into shared memory
359  */
360 HGLOBAL CLIPBOARD_GlobalDupMem( HGLOBAL hGlobalSrc )
361 {
362     HGLOBAL hGlobalDest;
363     PVOID pGlobalSrc, pGlobalDest;
364     DWORD cBytes;
365
366     if ( !hGlobalSrc )
367       return 0;
368
369     cBytes = GlobalSize(hGlobalSrc);
370     if ( 0 == cBytes )
371       return 0;
372
373     /* Turn on the DDESHARE and _MOVEABLE flags explicitly */
374     hGlobalDest = GlobalAlloc( GlobalFlags(hGlobalSrc) | GMEM_DDESHARE | GMEM_MOVEABLE,
375                                cBytes );
376     if ( !hGlobalDest )
377       return 0;
378
379     pGlobalSrc = GlobalLock(hGlobalSrc);
380     pGlobalDest = GlobalLock(hGlobalDest);
381     if ( !pGlobalSrc || !pGlobalDest )
382       return 0;
383
384     memcpy(pGlobalDest, pGlobalSrc, cBytes);
385
386     GlobalUnlock(hGlobalSrc);
387     GlobalUnlock(hGlobalDest);
388
389     return hGlobalDest;
390 }
391
392 /**************************************************************************
393  *                      CLIPBOARD_GetFormatName
394  *  Gets the format name associated with an ID
395  */
396 char * CLIPBOARD_GetFormatName(UINT wFormat, LPSTR buf, INT size)
397 {
398     LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
399
400     if (lpFormat)
401     {
402         if (buf)
403         {
404             strncpy(buf, lpFormat->Name, size);
405             CharLowerA(buf);
406         }
407
408         return lpFormat->Name;
409     }
410     else
411         return NULL;
412 }
413
414
415 /**************************************************************************
416  *                      CLIPBOARD_RenderFormat
417  */
418 static BOOL CLIPBOARD_RenderFormat(LPWINE_CLIPFORMAT lpFormat)
419 {
420   /*
421    * If WINE is not the selection owner, and the format is available
422    * we must ask the driver to render the data to the clipboard cache.
423    */
424   TRACE("enter format=%d\n", lpFormat->wFormatID);
425   if ( !USER_Driver.pIsSelectionOwner()
426        && USER_Driver.pIsClipboardFormatAvailable( lpFormat->wFormatID ) )
427   {
428     if ( !USER_Driver.pGetClipboardData( lpFormat->wFormatID ) )
429       return FALSE;
430   }
431   /*
432    * If Wine owns the clipboard, and the data is marked for delayed render,
433    * render it now.
434    */
435   else if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
436   {
437     if( IsWindow(hWndClipOwner) )
438     {
439       /* Send a WM_RENDERFORMAT message to notify the owner to render the
440        * data requested into the clipboard.
441        */
442       TRACE("Sending WM_RENDERFORMAT message\n");
443       SendMessageW( hWndClipOwner, WM_RENDERFORMAT, (WPARAM)lpFormat->wFormatID, 0 );
444     }
445     else
446     {
447       WARN("\thWndClipOwner (%04x) is lost!\n",
448            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("(%04x)...\n", hWnd);
755
756     if (!hClipLock)
757     {
758         hClipLock = GetCurrentTask();
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 (hClipLock == GetCurrentTask())
789     {
790         hWndClipWindow = 0;
791
792         if (bCBHasChanged && hWndViewer) SendMessageW( hWndViewer, WM_DRAWCLIPBOARD, 0, 0 );
793         hClipLock = 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 (hClipLock != GetCurrentTask())
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     hTaskClipOwner = GetCurrentTask();
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, %08x) !\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 %04x (type %i)\n",
1102                               lpRender->hData32, lpRender->wFormatID);
1103     return lpRender->hData32;
1104 }
1105
1106
1107 /**************************************************************************
1108  *              CountClipboardFormats (USER.143)
1109  */
1110 INT16 WINAPI CountClipboardFormats16(void)
1111 {
1112     return CountClipboardFormats();
1113 }
1114
1115
1116 /**************************************************************************
1117  *              CountClipboardFormats (USER32.@)
1118  */
1119 INT WINAPI CountClipboardFormats(void)
1120 {
1121     INT FormatCount = 0;
1122     LPWINE_CLIPFORMAT lpFormat = ClipFormats;
1123
1124     TRACE("()\n");
1125
1126     while(TRUE)
1127     {
1128         if (lpFormat == NULL) break;
1129
1130         if( lpFormat->wFormatID != CF_TEXT ) /* Don't count CF_TEXT */
1131         {
1132           /*
1133            * The format is available if either:
1134            * 1. The data is already in the cache.
1135            * 2. The selection is not owned by us(WINE) and the data is
1136            *    available to the clipboard driver.
1137            */
1138           if ( lpFormat->wDataPresent ||
1139                ( !USER_Driver.pIsSelectionOwner()
1140                  && USER_Driver.pIsClipboardFormatAvailable( lpFormat->wFormatID ) ) )
1141           {
1142               TRACE("\tdata found for format 0x%04x(%s)\n",
1143                     lpFormat->wFormatID, CLIPBOARD_GetFormatName(lpFormat->wFormatID, NULL, 0));
1144               FormatCount++;
1145           }
1146         }
1147
1148         lpFormat = lpFormat->NextFormat;
1149     }
1150
1151     /* these are equivalent, adjust the total */
1152     FormatCount += (ClipFormats[CF_UNICODETEXT-1].wDataPresent ||
1153                     ClipFormats[CF_TEXT-1].wDataPresent ||
1154                     ClipFormats[CF_OEMTEXT-1].wDataPresent) ? 1 : 0;
1155
1156     TRACE("\ttotal %d\n", FormatCount);
1157     return FormatCount;
1158 }
1159
1160 /**************************************************************************
1161  *              EnumClipboardFormats (USER.144)
1162  */
1163 UINT16 WINAPI EnumClipboardFormats16( UINT16 wFormat )
1164 {
1165     return EnumClipboardFormats( wFormat );
1166 }
1167
1168
1169 /**************************************************************************
1170  *              EnumClipboardFormats (USER32.@)
1171  */
1172 UINT WINAPI EnumClipboardFormats( UINT wFormat )
1173 {
1174     TRACE("(%04X)\n", wFormat);
1175
1176     if (CLIPBOARD_IsLocked())
1177     {
1178         WARN("Clipboard not opened by calling task!\n");
1179         return 0;
1180     }
1181
1182     return CLIPBOARD_EnumClipboardFormats(wFormat);
1183 }
1184
1185
1186 /**************************************************************************
1187  *              RegisterClipboardFormatA (USER32.@)
1188  */
1189 UINT WINAPI RegisterClipboardFormatA( LPCSTR FormatName )
1190 {
1191     LPWINE_CLIPFORMAT lpNewFormat;
1192     LPWINE_CLIPFORMAT lpFormat = ClipFormats;
1193
1194     if (FormatName == NULL) return 0;
1195
1196     TRACE("('%s') !\n", FormatName);
1197
1198     /* walk format chain to see if it's already registered */
1199
1200     while(TRUE)
1201     {
1202         if ( !strcasecmp(lpFormat->Name,FormatName) )
1203         {
1204              lpFormat->wRefCount++;
1205              return lpFormat->wFormatID;
1206         }
1207
1208         if ( lpFormat->NextFormat == NULL ) break;
1209
1210         lpFormat = lpFormat->NextFormat;
1211     }
1212
1213     /* allocate storage for new format entry */
1214
1215     lpNewFormat = (LPWINE_CLIPFORMAT)HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_CLIPFORMAT));
1216     if(lpNewFormat == NULL) {
1217         WARN("No more memory for a new format!\n");
1218         return 0;
1219     }
1220     lpFormat->NextFormat = lpNewFormat;
1221     lpNewFormat->wRefCount = 1;
1222
1223     if (!(lpNewFormat->Name = HeapAlloc(GetProcessHeap(), 0, strlen(FormatName)+1 )))
1224     {
1225         WARN("No more memory for the new format name!\n");
1226         HeapFree(GetProcessHeap(), 0, lpNewFormat);
1227         return 0;
1228     }
1229     strcpy( lpNewFormat->Name, FormatName );
1230     CharLowerA(lpNewFormat->Name);
1231
1232     lpNewFormat->wDataPresent = 0;
1233     lpNewFormat->hData16 = 0;
1234     lpNewFormat->hDataSrc32 = 0;
1235     lpNewFormat->hData32 = 0;
1236     lpNewFormat->drvData = 0;
1237     lpNewFormat->PrevFormat = lpFormat;
1238     lpNewFormat->NextFormat = NULL;
1239
1240     /* Pass on the registration request to the driver */
1241     lpNewFormat->wFormatID = USER_Driver.pRegisterClipboardFormat(lpNewFormat->Name);
1242
1243     TRACE("Registering format(%d): %s\n", lpNewFormat->wFormatID, FormatName);
1244     return lpNewFormat->wFormatID;
1245 }
1246
1247
1248 /**************************************************************************
1249  *              RegisterClipboardFormat (USER.145)
1250  */
1251 UINT16 WINAPI RegisterClipboardFormat16( LPCSTR FormatName )
1252 {
1253     return RegisterClipboardFormatA( FormatName );
1254 }
1255
1256
1257 /**************************************************************************
1258  *              RegisterClipboardFormatW (USER32.@)
1259  */
1260 UINT WINAPI RegisterClipboardFormatW( LPCWSTR formatName )
1261 {
1262     LPSTR aFormat = HEAP_strdupWtoA( GetProcessHeap(), 0, formatName );
1263     UINT ret = RegisterClipboardFormatA( aFormat );
1264     HeapFree( GetProcessHeap(), 0, aFormat );
1265     return ret;
1266 }
1267
1268
1269 /**************************************************************************
1270  *              GetClipboardFormatName (USER.146)
1271  */
1272 INT16 WINAPI GetClipboardFormatName16( UINT16 wFormat, LPSTR retStr, INT16 maxlen )
1273 {
1274     return GetClipboardFormatNameA( wFormat, retStr, maxlen );
1275 }
1276
1277
1278 /**************************************************************************
1279  *              GetClipboardFormatNameA (USER32.@)
1280  */
1281 INT WINAPI GetClipboardFormatNameA( UINT wFormat, LPSTR retStr, INT maxlen )
1282 {
1283     LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
1284
1285     TRACE("(%04X, %p, %d) !\n", wFormat, retStr, maxlen);
1286
1287     if (lpFormat == NULL || lpFormat->Name == NULL)
1288     {
1289         /* Check if another wine process already registered the format */
1290         if (wFormat && !USER_Driver.pGetClipboardFormatName(wFormat, retStr, maxlen))
1291         {
1292             RegisterClipboardFormatA(retStr); /* Make a cache entry */
1293             return strlen(retStr);
1294         }
1295         else
1296         {
1297             TRACE("wFormat=%d not found\n", wFormat);
1298             return 0;
1299         }
1300     }
1301
1302     TRACE("Name='%s' !\n", lpFormat->Name);
1303
1304     lstrcpynA( retStr, lpFormat->Name, maxlen );
1305     return strlen(retStr);
1306 }
1307
1308
1309 /**************************************************************************
1310  *              GetClipboardFormatNameW (USER32.@)
1311  */
1312 INT WINAPI GetClipboardFormatNameW( UINT wFormat, LPWSTR retStr, INT maxlen )
1313 {
1314     INT ret;
1315     LPSTR p = HeapAlloc( GetProcessHeap(), 0, maxlen );
1316     if(p == NULL) return 0; /* FIXME: is this the correct failure value? */
1317
1318     ret = GetClipboardFormatNameA( wFormat, p, maxlen );
1319
1320     if (maxlen > 0 && !MultiByteToWideChar( CP_ACP, 0, p, -1, retStr, maxlen ))
1321         retStr[maxlen-1] = 0;
1322     HeapFree( GetProcessHeap(), 0, p );
1323     return ret;
1324 }
1325
1326
1327 /**************************************************************************
1328  *              SetClipboardViewer (USER32.@)
1329  */
1330 HWND WINAPI SetClipboardViewer( HWND hWnd )
1331 {
1332     HWND hwndPrev = hWndViewer;
1333
1334     TRACE("(%04x): returning %04x\n", hWnd, hwndPrev);
1335
1336     hWndViewer = WIN_GetFullHandle( hWnd );
1337     return hwndPrev;
1338 }
1339
1340
1341 /**************************************************************************
1342  *              GetClipboardViewer (USER32.@)
1343  */
1344 HWND WINAPI GetClipboardViewer(void)
1345 {
1346     TRACE("()\n");
1347     return hWndViewer;
1348 }
1349
1350
1351 /**************************************************************************
1352  *              ChangeClipboardChain (USER32.@)
1353  */
1354 BOOL WINAPI ChangeClipboardChain(HWND hWnd, HWND hWndNext)
1355 {
1356     BOOL bRet = 0;
1357
1358     FIXME("(0x%04x, 0x%04x): stub?\n", hWnd, hWndNext);
1359
1360     if( hWndViewer )
1361         bRet = !SendMessageW( hWndViewer, WM_CHANGECBCHAIN, (WPARAM)hWnd, (LPARAM)hWndNext );
1362     else
1363         WARN("hWndViewer is lost\n");
1364
1365     if( WIN_GetFullHandle(hWnd) == hWndViewer ) hWndViewer = WIN_GetFullHandle( hWndNext );
1366
1367     return bRet;
1368 }
1369
1370
1371 /**************************************************************************
1372  *              IsClipboardFormatAvailable (USER.193)
1373  */
1374 BOOL16 WINAPI IsClipboardFormatAvailable16( UINT16 wFormat )
1375 {
1376     return IsClipboardFormatAvailable( wFormat );
1377 }
1378
1379
1380 /**************************************************************************
1381  *              IsClipboardFormatAvailable (USER32.@)
1382  */
1383 BOOL WINAPI IsClipboardFormatAvailable( UINT wFormat )
1384 {
1385     BOOL bRet;
1386
1387     if (wFormat == 0)  /* Reject this case quickly */
1388         bRet = FALSE;
1389     else
1390     {
1391         UINT iret = CLIPBOARD_EnumClipboardFormats(wFormat - 1);
1392         if ((wFormat == CF_TEXT) || (wFormat == CF_OEMTEXT) || (wFormat == CF_UNICODETEXT))
1393             bRet = ((iret == CF_TEXT) || (iret == CF_OEMTEXT) || (iret == CF_UNICODETEXT));
1394         else
1395             bRet = iret == wFormat;
1396     }
1397     TRACE("(%04X)- ret(%d)\n", wFormat, bRet);
1398     return bRet;
1399 }
1400
1401
1402 /**************************************************************************
1403  *              GetOpenClipboardWindow (USER32.@)
1404  *  FIXME: This wont work if an external app owns the selection
1405  */
1406 HWND WINAPI GetOpenClipboardWindow(void)
1407 {
1408     TRACE("()\n");
1409     return hWndClipWindow;
1410 }
1411
1412
1413 /**************************************************************************
1414  *              GetPriorityClipboardFormat (USER32.@)
1415  */
1416 INT WINAPI GetPriorityClipboardFormat( UINT *list, INT nCount )
1417 {
1418     int i;
1419     TRACE("()\n");
1420
1421     if(CountClipboardFormats() == 0) return 0;
1422
1423     for (i = 0; i < nCount; i++)
1424         if (IsClipboardFormatAvailable( list[i] )) return list[i];
1425     return -1;
1426 }
1427
1428
1429 /**************************************************************************
1430  *              GetClipboardSequenceNumber (USER32.@)
1431  * Supported on Win2k/Win98
1432  * MSDN: Windows clipboard code keeps a serial number for the clipboard
1433  * for each window station.  The number is incremented whenever the
1434  * contents change or are emptied.
1435  * If you do not have WINSTA_ACCESSCLIPBOARD then the function returns 0
1436  */
1437 DWORD WINAPI GetClipboardSequenceNumber(VOID)
1438 {
1439         FIXME("Returning 0, see windows/clipboard.c\n");
1440         /* FIXME: Use serial numbers */
1441         return 0;
1442 }