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