Fixed some warnings. removed some unneccessary includes, removed one
[wine] / windows / clipboard.c
1 /*
2  * WINE clipboard function handling
3  *
4  * Copyright 1994 Martin Ayotte
5  *           1996 Alex Korobka
6  *
7  */
8
9 #include <stdlib.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <fcntl.h>
13 #include <unistd.h>
14 #include <string.h>
15 #include "winuser.h"
16 #include "wine/winuser16.h"
17 #include "heap.h"
18 #include "task.h"
19 #include "message.h"
20 #include "clipboard.h"
21 #include "xmalloc.h"
22 #include "debug.h"
23
24 #ifndef X_DISPLAY_MISSING
25 extern CLIPBOARD_DRIVER X11DRV_CLIPBOARD_Driver;
26 #else /* X_DISPLAY_MISSING */
27 extern CLIPBOARD_DRIVER TTYDRV_CLIPBOARD_Driver;
28 #endif /* X_DISPLAY_MISSING */
29
30 #define  CF_REGFORMATBASE       0xC000
31
32 /**************************************************************************
33  *                      internal variables
34  */
35
36 static HQUEUE16 hqClipLock   = 0;
37 static BOOL bCBHasChanged  = FALSE;
38
39 HWND hWndClipOwner  = 0;   /* current clipboard owner */
40 HWND hWndClipWindow = 0;   /* window that opened clipboard */
41 static HWND hWndViewer     = 0;   /* start of viewers chain */
42
43 static WORD LastRegFormat = CF_REGFORMATBASE;
44
45 WINE_CLIPFORMAT ClipFormats[16]  = {
46     { CF_TEXT, 1, 0, "Text", (HANDLE)NULL, 0, NULL, &ClipFormats[1] , (HANDLE16)NULL},
47     { CF_BITMAP, 1, 0, "Bitmap", (HANDLE)NULL, 0, &ClipFormats[0], &ClipFormats[2] , (HANDLE16)NULL},
48     { CF_METAFILEPICT, 1, 0, "MetaFile Picture", (HANDLE)NULL, 0, &ClipFormats[1], &ClipFormats[3] , (HANDLE16)NULL},
49     { CF_SYLK, 1, 0, "Sylk", (HANDLE)NULL, 0, &ClipFormats[2], &ClipFormats[4] , (HANDLE16)NULL},
50     { CF_DIF, 1, 0, "DIF", (HANDLE)NULL, 0, &ClipFormats[3], &ClipFormats[5] , (HANDLE16)NULL},
51     { CF_TIFF, 1, 0, "TIFF", (HANDLE)NULL, 0, &ClipFormats[4], &ClipFormats[6] , (HANDLE16)NULL},
52     { CF_OEMTEXT, 1, 0, "OEM Text", (HANDLE)NULL, 0, &ClipFormats[5], &ClipFormats[7] , (HANDLE16)NULL},
53     { CF_DIB, 1, 0, "DIB", (HANDLE)NULL, 0, &ClipFormats[6], &ClipFormats[8] , (HANDLE16)NULL},
54     { CF_PALETTE, 1, 0, "Palette", (HANDLE)NULL, 0, &ClipFormats[7], &ClipFormats[9] , (HANDLE16)NULL},
55     { CF_PENDATA, 1, 0, "PenData", (HANDLE)NULL, 0, &ClipFormats[8], &ClipFormats[10] , (HANDLE16)NULL},
56     { CF_RIFF, 1, 0, "RIFF", (HANDLE)NULL, 0, &ClipFormats[9], &ClipFormats[11] , (HANDLE16)NULL},
57     { CF_WAVE, 1, 0, "Wave", (HANDLE)NULL, 0, &ClipFormats[10], &ClipFormats[12] , (HANDLE16)NULL},
58     { CF_OWNERDISPLAY, 1, 0, "Owner Display", (HANDLE)NULL, 0, &ClipFormats[11], &ClipFormats[13] , (HANDLE16)NULL},
59     { CF_DSPTEXT, 1, 0, "DSPText", (HANDLE)NULL, 0, &ClipFormats[12], &ClipFormats[14] , (HANDLE16)NULL},
60     { CF_DSPMETAFILEPICT, 1, 0, "DSPMetaFile Picture", (HANDLE)NULL, 0, &ClipFormats[13], &ClipFormats[15] , (HANDLE16)NULL},
61     { CF_DSPBITMAP, 1, 0, "DSPBitmap", (HANDLE)NULL, 0, &ClipFormats[14], NULL , (HANDLE16)NULL}
62     };
63
64 static LPWINE_CLIPFORMAT __lookup_format( LPWINE_CLIPFORMAT lpFormat, WORD wID )
65 {
66     while(TRUE)
67     {
68         if (lpFormat == NULL ||
69             lpFormat->wFormatID == wID) break;
70         lpFormat = lpFormat->NextFormat;
71     }
72     return lpFormat;
73 }
74
75
76 /**************************************************************************
77  *              CLIPBOARD_GetDriver
78  */
79 CLIPBOARD_DRIVER *CLIPBOARD_GetDriver()
80 {
81 #ifndef X_DISPLAY_MISSING
82   return &X11DRV_CLIPBOARD_Driver;
83 #else /* X_DISPLAY_MISSING */
84   return &TTYDRV_CLIPBOARD_Driver;
85 #endif /* X_DISPLAY_MISSING */
86 };
87
88 /**************************************************************************
89  *                      CLIPBOARD_ResetLock
90  */
91 void CLIPBOARD_ResetLock( HQUEUE16 hqCurrent, HQUEUE16 hqNew )
92 {
93     if( hqClipLock == hqCurrent )
94     {
95         if( hqNew )
96             hqClipLock = hqNew;
97         else
98         {
99             hWndClipOwner = 0;
100             hWndClipWindow = 0;
101             EmptyClipboard();
102             hqClipLock = 0;
103         }
104     }
105 }
106
107
108 /**************************************************************************
109  *                      CLIPBOARD_DeleteRecord
110  */
111 void CLIPBOARD_DeleteRecord(LPWINE_CLIPFORMAT lpFormat, BOOL bChange)
112 {
113     if( (lpFormat->wFormatID >= CF_GDIOBJFIRST &&
114          lpFormat->wFormatID <= CF_GDIOBJLAST) || lpFormat->wFormatID == CF_BITMAP )
115     {
116       if (lpFormat->hData32)
117         DeleteObject(lpFormat->hData32);
118       if (lpFormat->hData16)
119         DeleteObject16(lpFormat->hData16);
120     }
121     else if( lpFormat->wFormatID == CF_METAFILEPICT )
122     {
123       if (lpFormat->hData32)
124       {
125         DeleteMetaFile( ((METAFILEPICT *)GlobalLock( lpFormat->hData32 ))->hMF );
126         GlobalFree(lpFormat->hData32);
127         if (lpFormat->hData16)
128           /* HMETAFILE16 and HMETAFILE32 are apparently the same thing, 
129              and a shallow copy is enough to share a METAFILEPICT
130              structure between 16bit and 32bit clipboards.  The MetaFile
131              should of course only be deleted once. */
132           GlobalFree16(lpFormat->hData16);
133       }
134       else if (lpFormat->hData16)
135       {
136         DeleteMetaFile16( ((METAFILEPICT16 *)GlobalLock16( lpFormat->hData16 ))->hMF );
137         GlobalFree16(lpFormat->hData16);
138       }
139     }
140     else 
141     {
142       if (lpFormat->hData32)
143         GlobalFree(lpFormat->hData32);
144       if (lpFormat->hData16)
145         GlobalFree16(lpFormat->hData16);
146     }
147
148     lpFormat->wDataPresent = 0; 
149     lpFormat->hData16 = 0;
150     lpFormat->hData32 = 0;
151
152     if( bChange ) bCBHasChanged = TRUE;
153 }
154
155 /**************************************************************************
156  *                      CLIPBOARD_IsPresent
157  */
158 BOOL CLIPBOARD_IsPresent(WORD wFormat)
159 {
160     /* special case */
161
162     if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
163         return ClipFormats[CF_TEXT-1].wDataPresent ||
164                ClipFormats[CF_OEMTEXT-1].wDataPresent;
165     else
166     {
167         LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
168         if( lpFormat ) return (lpFormat->wDataPresent);
169     }
170     return FALSE;
171 }
172
173 /**************************************************************************
174  *            OpenClipboard16   (USER.137)
175  */
176 BOOL16 WINAPI OpenClipboard16( HWND16 hWnd )
177 {
178     return OpenClipboard( hWnd );
179 }
180
181
182 /**************************************************************************
183  *            OpenClipboard32   (USER32.407)
184  *
185  * Note: Netscape uses NULL hWnd to open the clipboard.
186  */
187 BOOL WINAPI OpenClipboard( HWND hWnd )
188 {
189     BOOL bRet;
190
191     TRACE(clipboard,"(%04x)...\n", hWnd);
192
193     if (!hqClipLock)
194     {
195          hqClipLock = GetFastQueue16();
196          hWndClipWindow = hWnd;
197          bCBHasChanged = FALSE;
198          bRet = TRUE;
199     }
200     else bRet = FALSE;
201
202     TRACE(clipboard,"   returning %i\n", bRet);
203     return bRet;
204 }
205
206
207 /**************************************************************************
208  *            CloseClipboard16   (USER.138)
209  */
210 BOOL16 WINAPI CloseClipboard16(void)
211 {
212     return CloseClipboard();
213 }
214
215
216 /**************************************************************************
217  *            CloseClipboard32   (USER32.54)
218  */
219 BOOL WINAPI CloseClipboard(void)
220 {
221     TRACE(clipboard,"!\n");
222
223     if (hqClipLock == GetFastQueue16())
224     {
225         hWndClipWindow = 0;
226
227         if (bCBHasChanged && hWndViewer) 
228             SendMessage16(hWndViewer, WM_DRAWCLIPBOARD, 0, 0L);
229         hqClipLock = 0;
230     }
231     return TRUE;
232 }
233
234
235 /**************************************************************************
236  *            EmptyClipboard16   (USER.139)
237  */
238 BOOL16 WINAPI EmptyClipboard16(void)
239 {
240     return EmptyClipboard();
241 }
242
243
244 /**************************************************************************
245  *            EmptyClipboard32   (USER32.169)
246  */
247 BOOL WINAPI EmptyClipboard(void)
248 {
249     LPWINE_CLIPFORMAT lpFormat = ClipFormats; 
250
251     TRACE(clipboard,"(void)\n");
252
253     if (hqClipLock != GetFastQueue16()) return FALSE;
254
255     /* destroy private objects */
256
257     if (hWndClipOwner)
258         SendMessage16(hWndClipOwner, WM_DESTROYCLIPBOARD, 0, 0L);
259   
260     while(lpFormat) 
261     {
262         if ( lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32 )
263              CLIPBOARD_DeleteRecord( lpFormat, TRUE );
264
265         lpFormat = lpFormat->NextFormat;
266     }
267
268     hWndClipOwner = hWndClipWindow;
269
270     CLIPBOARD_GetDriver()->pEmptyClipboard();
271
272     return TRUE;
273 }
274
275
276 /**************************************************************************
277  *            GetClipboardOwner16   (USER.140)
278  */
279 HWND16 WINAPI GetClipboardOwner16(void)
280 {
281     return hWndClipOwner;
282 }
283
284
285 /**************************************************************************
286  *            GetClipboardOwner32   (USER32.225)
287  */
288 HWND WINAPI GetClipboardOwner(void)
289 {
290     return hWndClipOwner;
291 }
292
293
294 /**************************************************************************
295  *            SetClipboardData16   (USER.141)
296  */
297 HANDLE16 WINAPI SetClipboardData16( UINT16 wFormat, HANDLE16 hData )
298 {
299     LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
300
301     TRACE(clipboard, "(%04X, %04x) !\n", wFormat, hData);
302
303     /* NOTE: If the hData is zero and current owner doesn't match
304      * the window that opened the clipboard then this application
305      * is screwed because WM_RENDERFORMAT will go to the owner
306      * (to become the owner it must call EmptyClipboard() before
307      *  adding new data).
308      */
309
310     if( (hqClipLock != GetFastQueue16()) || !lpFormat ||
311         (!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) ) return 0; 
312
313     CLIPBOARD_GetDriver()->pSetClipboardData(wFormat);
314
315     if ( lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32 ) 
316     {
317         CLIPBOARD_DeleteRecord(lpFormat, TRUE);
318
319         /* delete existing CF_TEXT/CF_OEMTEXT aliases */
320
321         if( wFormat == CF_TEXT 
322             && ( ClipFormats[CF_OEMTEXT-1].hData16 
323                  ||  ClipFormats[CF_OEMTEXT-1].hData32 )
324             && !ClipFormats[CF_OEMTEXT-1].wDataPresent )
325             CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
326         if( wFormat == CF_OEMTEXT 
327             && ( ClipFormats[CF_OEMTEXT-1].hData16 
328                  ||  ClipFormats[CF_OEMTEXT-1].hData32 )
329             && !ClipFormats[CF_TEXT-1].wDataPresent )
330             CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
331     }
332
333     bCBHasChanged = TRUE;
334     lpFormat->wDataPresent = 1;
335     lpFormat->hData16 = hData;          /* 0 is legal, see WM_RENDERFORMAT */
336     lpFormat->hData32 = 0;
337
338     return lpFormat->hData16;
339 }
340
341
342 /**************************************************************************
343  *            SetClipboardData32   (USER32.470)
344  */
345 HANDLE WINAPI SetClipboardData( UINT wFormat, HANDLE hData )
346 {
347     LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
348
349     TRACE(clipboard, "(%08X, %08x) !\n", wFormat, hData);
350
351     /* NOTE: If the hData is zero and current owner doesn't match
352      * the window that opened the clipboard then this application
353      * is screwed because WM_RENDERFORMAT will go to the owner
354      * (to become the owner it must call EmptyClipboard() before
355      *  adding new data).
356      */
357
358     if( (hqClipLock != GetFastQueue16()) || !lpFormat ||
359         (!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) ) return 0; 
360
361     CLIPBOARD_GetDriver()->pSetClipboardData(wFormat);
362
363     if ( lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32 ) 
364     {
365         CLIPBOARD_DeleteRecord(lpFormat, TRUE);
366
367         /* delete existing CF_TEXT/CF_OEMTEXT aliases */
368
369         if( wFormat == CF_TEXT 
370             && ( ClipFormats[CF_OEMTEXT-1].hData16 
371                  ||  ClipFormats[CF_OEMTEXT-1].hData32 )
372             && !ClipFormats[CF_OEMTEXT-1].wDataPresent )
373             CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
374         if( wFormat == CF_OEMTEXT 
375             && ( ClipFormats[CF_OEMTEXT-1].hData16 
376                  ||  ClipFormats[CF_OEMTEXT-1].hData32 )
377             && !ClipFormats[CF_TEXT-1].wDataPresent )
378             CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
379     }
380
381     bCBHasChanged = TRUE;
382     lpFormat->wDataPresent = 1;
383     lpFormat->hData32 = hData;          /* 0 is legal, see WM_RENDERFORMAT */
384     lpFormat->hData16 = 0;
385
386     return lpFormat->hData32;
387 }
388
389
390 /**************************************************************************
391  *                      CLIPBOARD_RenderFormat
392  */
393 static BOOL CLIPBOARD_RenderFormat(LPWINE_CLIPFORMAT lpFormat)
394 {
395   if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
396   {
397     if( IsWindow(hWndClipOwner) )
398       SendMessage16(hWndClipOwner,WM_RENDERFORMAT,
399                     (WPARAM16)lpFormat->wFormatID,0L);
400     else
401     {
402       WARN(clipboard, "\thWndClipOwner (%04x) is lost!\n", 
403            hWndClipOwner);
404       hWndClipOwner = 0; lpFormat->wDataPresent = 0;
405       return FALSE;
406     }
407   }
408   return (lpFormat->hData16 || lpFormat->hData32) ? TRUE : FALSE;
409 }
410
411 /**************************************************************************
412  *                      CLIPBOARD_RenderText
413  *
414  * Convert text between UNIX and DOS formats.
415  */
416 static BOOL CLIPBOARD_RenderText(LPWINE_CLIPFORMAT lpTarget, LPWINE_CLIPFORMAT lpSource)
417 {
418     UINT16 size;
419     LPCSTR lpstrS; 
420     LPSTR  lpstrT;
421
422     if (lpSource->hData32)
423     {
424       size = GlobalSize( lpSource->hData32 );
425       lpstrS = (LPSTR)GlobalLock(lpSource->hData32);
426     }
427     else
428     {
429       size = GlobalSize16( lpSource->hData16 );
430       lpstrS = (LPSTR)GlobalLock16(lpSource->hData16);
431     }
432
433     if( !lpstrS ) return FALSE;
434     TRACE(clipboard,"\tconverting from '%s' to '%s', %i chars\n",
435                                       lpSource->Name, lpTarget->Name, size);
436
437     lpTarget->hData32 = GlobalAlloc(GMEM_ZEROINIT, size); 
438     lpstrT = (LPSTR)GlobalLock(lpTarget->hData32);
439
440     if( lpstrT )
441     {
442         if( lpSource->wFormatID == CF_TEXT )
443             CharToOemBuffA(lpstrS, lpstrT, size);
444         else
445             OemToCharBuffA(lpstrS, lpstrT, size);
446         TRACE(clipboard,"\tgot %s\n", lpstrT);
447         GlobalUnlock(lpTarget->hData32);
448         if (lpSource->hData32)
449           GlobalUnlock(lpSource->hData32);
450         else
451           GlobalUnlock16(lpSource->hData16);
452         return TRUE;
453     }
454
455     lpTarget->hData32 = 0;
456     if (lpSource->hData32)
457       GlobalUnlock(lpSource->hData32);
458     else
459       GlobalUnlock16(lpSource->hData16);
460     return FALSE;
461 }
462
463 /**************************************************************************
464  *             GetClipboardData16   (USER.142)
465  */
466 HANDLE16 WINAPI GetClipboardData16( UINT16 wFormat )
467 {
468     LPWINE_CLIPFORMAT lpRender = ClipFormats; 
469     LPWINE_CLIPFORMAT lpUpdate = NULL;
470
471     if (hqClipLock != GetFastQueue16()) return 0;
472
473     TRACE(clipboard,"(%04X)\n", wFormat);
474
475     if( wFormat == CF_TEXT && !lpRender[CF_TEXT-1].wDataPresent 
476                            &&  lpRender[CF_OEMTEXT-1].wDataPresent )
477     {
478         lpRender = &ClipFormats[CF_OEMTEXT-1];
479         lpUpdate = &ClipFormats[CF_TEXT-1];
480
481         TRACE(clipboard,"\tOEMTEXT -> TEXT\n");
482     }
483     else if( wFormat == CF_OEMTEXT && !lpRender[CF_OEMTEXT-1].wDataPresent
484                                    &&  lpRender[CF_TEXT-1].wDataPresent )
485     {
486         lpRender = &ClipFormats[CF_TEXT-1];
487         lpUpdate = &ClipFormats[CF_OEMTEXT-1];
488         
489         TRACE(clipboard,"\tTEXT -> OEMTEXT\n");
490     }
491     else
492     {
493         lpRender = __lookup_format( ClipFormats, wFormat );
494         lpUpdate = lpRender;
495     }
496    
497     if( !lpRender || !CLIPBOARD_RenderFormat(lpRender) ) return 0; 
498     if( lpUpdate != lpRender && !lpUpdate->hData16 && !lpUpdate->hData32 ) 
499         CLIPBOARD_RenderText(lpUpdate, lpRender);
500
501     if( lpUpdate->hData32 && !lpUpdate->hData16 )
502     {
503       int size;
504       if( lpUpdate->wFormatID == CF_METAFILEPICT )
505         size = sizeof( METAFILEPICT16 );
506       else
507         size = GlobalSize(lpUpdate->hData32);
508       lpUpdate->hData16 = GlobalAlloc16(GMEM_ZEROINIT, size);
509       if( !lpUpdate->hData16 )
510         ERR(clipboard, "(%04X) -- not enough memory in 16b heap\n", wFormat);
511       else
512       {
513       if( lpUpdate->wFormatID == CF_METAFILEPICT )
514       {
515         FIXME(clipboard,"\timplement function CopyMetaFilePict32to16\n");
516         FIXME(clipboard,"\tin the appropriate file.\n");
517 #ifdef SOMEONE_IMPLEMENTED_ME
518         CopyMetaFilePict32to16( GlobalLock16(lpUpdate->hData16), 
519                                 GlobalLock(lpUpdate->hData32) );
520 #endif
521       }
522       else
523       {
524         memcpy( GlobalLock16(lpUpdate->hData16), 
525                 GlobalLock(lpUpdate->hData32), 
526                 size );
527       }
528         GlobalUnlock16(lpUpdate->hData16);
529         GlobalUnlock(lpUpdate->hData32);
530       }
531     }
532
533     TRACE(clipboard,"\treturning %04x (type %i)\n", 
534                               lpUpdate->hData16, lpUpdate->wFormatID);
535     return lpUpdate->hData16;
536 }
537
538
539 /**************************************************************************
540  *             GetClipboardData32   (USER32.222)
541  */
542 HANDLE WINAPI GetClipboardData( UINT wFormat )
543 {
544     LPWINE_CLIPFORMAT lpRender = ClipFormats; 
545     LPWINE_CLIPFORMAT lpUpdate = NULL;
546
547     if (hqClipLock != GetFastQueue16()) return 0;
548
549     TRACE(clipboard,"(%08X)\n", wFormat);
550
551     if( wFormat == CF_TEXT && !lpRender[CF_TEXT-1].wDataPresent 
552                            &&  lpRender[CF_OEMTEXT-1].wDataPresent )
553     {
554         lpRender = &ClipFormats[CF_OEMTEXT-1];
555         lpUpdate = &ClipFormats[CF_TEXT-1];
556
557         TRACE(clipboard,"\tOEMTEXT -> TEXT\n");
558     }
559     else if( wFormat == CF_OEMTEXT && !lpRender[CF_OEMTEXT-1].wDataPresent
560                                    &&  lpRender[CF_TEXT-1].wDataPresent )
561     {
562         lpRender = &ClipFormats[CF_TEXT-1];
563         lpUpdate = &ClipFormats[CF_OEMTEXT-1];
564         
565         TRACE(clipboard,"\tTEXT -> OEMTEXT\n");
566     }
567     else
568     {
569         lpRender = __lookup_format( ClipFormats, wFormat );
570         lpUpdate = lpRender;
571     }
572    
573     if( !lpRender || !CLIPBOARD_RenderFormat(lpRender) ) return 0; 
574     if( lpUpdate != lpRender && !lpUpdate->hData16 && !lpUpdate->hData32 ) 
575         CLIPBOARD_RenderText(lpUpdate, lpRender);
576
577     if( lpUpdate->hData16 && !lpUpdate->hData32 )
578     {
579       int size;
580       if( lpUpdate->wFormatID == CF_METAFILEPICT )
581         size = sizeof( METAFILEPICT );
582       else
583         size = GlobalSize16(lpUpdate->hData16);
584       lpUpdate->hData32 = GlobalAlloc(GMEM_ZEROINIT, size); 
585       if( lpUpdate->wFormatID == CF_METAFILEPICT )
586       {
587         FIXME(clipboard,"\timplement function CopyMetaFilePict16to32\n");
588         FIXME(clipboard,"\tin the appropriate file.\n");
589 #ifdef SOMEONE_IMPLEMENTED_ME
590         CopyMetaFilePict16to32( GlobalLock16(lpUpdate->hData32), 
591                                 GlobalLock(lpUpdate->hData16) );
592 #endif
593       }
594       else
595       {
596         memcpy( GlobalLock(lpUpdate->hData32), 
597                 GlobalLock16(lpUpdate->hData16), 
598                 size );
599       }
600       GlobalUnlock(lpUpdate->hData32);
601       GlobalUnlock16(lpUpdate->hData16);
602     }
603
604     TRACE(clipboard,"\treturning %04x (type %i)\n", 
605                               lpUpdate->hData32, lpUpdate->wFormatID);
606     return lpUpdate->hData32;
607 }
608
609 /**************************************************************************
610  *           CountClipboardFormats16   (USER.143)
611  */
612 INT16 WINAPI CountClipboardFormats16(void)
613 {
614     return CountClipboardFormats();
615 }
616
617
618 /**************************************************************************
619  *           CountClipboardFormats32   (USER32.63)
620  */
621 INT WINAPI CountClipboardFormats(void)
622 {
623     INT FormatCount = 0;
624     LPWINE_CLIPFORMAT lpFormat = ClipFormats; 
625
626     TRACE(clipboard,"(void)\n");
627
628     /* FIXME: Returns BOOL32 */
629     CLIPBOARD_GetDriver()->pRequestSelection();
630
631     FormatCount += abs(lpFormat[CF_TEXT-1].wDataPresent -
632                        lpFormat[CF_OEMTEXT-1].wDataPresent); 
633
634     while(TRUE) 
635     {
636         if (lpFormat == NULL) break;
637         if (lpFormat->wDataPresent) 
638         {
639             TRACE(clipboard, "\tdata found for format %i\n", lpFormat->wFormatID);
640             FormatCount++;
641         }
642         lpFormat = lpFormat->NextFormat;
643     }
644
645     TRACE(clipboard,"\ttotal %d\n", FormatCount);
646     return FormatCount;
647 }
648
649
650 /**************************************************************************
651  *            EnumClipboardFormats16   (USER.144)
652  */
653 UINT16 WINAPI EnumClipboardFormats16( UINT16 wFormat )
654 {
655     return EnumClipboardFormats( wFormat );
656 }
657
658
659 /**************************************************************************
660  *            EnumClipboardFormats32   (USER32.179)
661  */
662 UINT WINAPI EnumClipboardFormats( UINT wFormat )
663 {
664     LPWINE_CLIPFORMAT lpFormat = ClipFormats; 
665
666     TRACE(clipboard,"(%04X)\n", wFormat);
667
668     if( hqClipLock != GetFastQueue16() ) return 0;
669
670     if( (!wFormat || wFormat == CF_TEXT || wFormat == CF_OEMTEXT) ) 
671         CLIPBOARD_GetDriver()->pRequestSelection();
672
673     if (wFormat == 0)
674     {
675         if (lpFormat->wDataPresent || ClipFormats[CF_OEMTEXT-1].wDataPresent) 
676             return lpFormat->wFormatID;
677         else 
678             wFormat = lpFormat->wFormatID; /* and CF_TEXT is not available */
679     }
680
681     /* walk up to the specified format record */
682
683     if( !(lpFormat = __lookup_format( lpFormat, wFormat )) ) return 0;
684
685     /* find next format with available data */
686
687     lpFormat = lpFormat->NextFormat;
688     while(TRUE) 
689     {
690         if (lpFormat == NULL) return 0;
691         if (lpFormat->wDataPresent || (lpFormat->wFormatID == CF_OEMTEXT && 
692                                        ClipFormats[CF_TEXT-1].wDataPresent)) 
693             break;
694         lpFormat = lpFormat->NextFormat;
695     }
696
697     return lpFormat->wFormatID;
698 }
699
700
701 /**************************************************************************
702  *            RegisterClipboardFormat16  (USER.145)
703  */
704 UINT16 WINAPI RegisterClipboardFormat16( LPCSTR FormatName )
705 {
706     LPWINE_CLIPFORMAT lpNewFormat; 
707     LPWINE_CLIPFORMAT lpFormat = ClipFormats; 
708
709     if (FormatName == NULL) return 0;
710
711     TRACE(clipboard,"('%s') !\n", FormatName);
712
713     /* walk format chain to see if it's already registered */
714
715     while(TRUE) 
716     {
717         if ( !strcmp(lpFormat->Name,FormatName) )
718         {
719              lpFormat->wRefCount++;
720              return lpFormat->wFormatID;
721         }
722  
723         if ( lpFormat->NextFormat == NULL ) break;
724
725         lpFormat = lpFormat->NextFormat;
726     }
727
728     /* allocate storage for new format entry */
729
730     lpNewFormat = (LPWINE_CLIPFORMAT)xmalloc(sizeof(WINE_CLIPFORMAT));
731     lpFormat->NextFormat = lpNewFormat;
732     lpNewFormat->wFormatID = LastRegFormat;
733     lpNewFormat->wRefCount = 1;
734
735     lpNewFormat->Name = (LPSTR)xmalloc(strlen(FormatName) + 1);
736     strcpy(lpNewFormat->Name, FormatName);
737
738     lpNewFormat->wDataPresent = 0;
739     lpNewFormat->hData16 = 0;
740     lpNewFormat->hData32 = 0;
741     lpNewFormat->BufSize = 0;
742     lpNewFormat->PrevFormat = lpFormat;
743     lpNewFormat->NextFormat = NULL;
744
745     return LastRegFormat++;
746 }
747
748
749 /**************************************************************************
750  *            RegisterClipboardFormat32A   (USER32.431)
751  */
752 UINT WINAPI RegisterClipboardFormatA( LPCSTR formatName )
753 {
754     return RegisterClipboardFormat16( formatName );
755 }
756
757
758 /**************************************************************************
759  *            RegisterClipboardFormat32W   (USER32.432)
760  */
761 UINT WINAPI RegisterClipboardFormatW( LPCWSTR formatName )
762 {
763     LPSTR aFormat = HEAP_strdupWtoA( GetProcessHeap(), 0, formatName );
764     UINT ret = RegisterClipboardFormatA( aFormat );
765     HeapFree( GetProcessHeap(), 0, aFormat );
766     return ret;
767 }
768
769 /**************************************************************************
770  *            GetClipboardFormatName16   (USER.146)
771  */
772 INT16 WINAPI GetClipboardFormatName16( UINT16 wFormat, LPSTR retStr, INT16 maxlen )
773 {
774     return GetClipboardFormatNameA( wFormat, retStr, maxlen );
775 }
776
777
778 /**************************************************************************
779  *            GetClipboardFormatName32A   (USER32.223)
780  */
781 INT WINAPI GetClipboardFormatNameA( UINT wFormat, LPSTR retStr, INT maxlen )
782 {
783     LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
784
785     TRACE(clipboard, "(%04X, %p, %d) !\n", wFormat, retStr, maxlen);
786
787     if (lpFormat == NULL || lpFormat->Name == NULL || 
788         lpFormat->wFormatID < CF_REGFORMATBASE) return 0;
789
790     TRACE(clipboard, "Name='%s' !\n", lpFormat->Name);
791
792     lstrcpynA( retStr, lpFormat->Name, maxlen );
793     return strlen(retStr);
794 }
795
796
797 /**************************************************************************
798  *            GetClipboardFormatName32W   (USER32.224)
799  */
800 INT WINAPI GetClipboardFormatNameW( UINT wFormat, LPWSTR retStr, INT maxlen )
801 {
802     LPSTR p = HEAP_xalloc( GetProcessHeap(), 0, maxlen );
803     INT ret = GetClipboardFormatNameA( wFormat, p, maxlen );
804     lstrcpynAtoW( retStr, p, maxlen );
805     HeapFree( GetProcessHeap(), 0, p );
806     return ret;
807 }
808
809
810 /**************************************************************************
811  *            SetClipboardViewer16   (USER.147)
812  */
813 HWND16 WINAPI SetClipboardViewer16( HWND16 hWnd )
814 {
815     return SetClipboardViewer( hWnd );
816 }
817
818
819 /**************************************************************************
820  *            SetClipboardViewer32   (USER32.471)
821  */
822 HWND WINAPI SetClipboardViewer( HWND hWnd )
823 {
824     HWND hwndPrev = hWndViewer;
825
826     TRACE(clipboard,"(%04x): returning %04x\n", hWnd, hwndPrev);
827
828     hWndViewer = hWnd;
829     return hwndPrev;
830 }
831
832
833 /**************************************************************************
834  *           GetClipboardViewer16   (USER.148)
835  */
836 HWND16 WINAPI GetClipboardViewer16(void)
837 {
838     return hWndViewer;
839 }
840
841
842 /**************************************************************************
843  *           GetClipboardViewer32   (USER32.226)
844  */
845 HWND WINAPI GetClipboardViewer(void)
846 {
847     return hWndViewer;
848 }
849
850
851 /**************************************************************************
852  *           ChangeClipboardChain16   (USER.149)
853  */
854 BOOL16 WINAPI ChangeClipboardChain16(HWND16 hWnd, HWND16 hWndNext)
855 {
856     return ChangeClipboardChain(hWnd, hWndNext);
857 }
858
859 /**************************************************************************
860  *           ChangeClipboardChain32   (USER32.22)
861  */
862 BOOL WINAPI ChangeClipboardChain(HWND hWnd, HWND hWndNext)
863 {
864     BOOL bRet = 0;
865
866     FIXME(clipboard, "(0x%04x, 0x%04x): stub?\n", hWnd, hWndNext);
867
868     if( hWndViewer )
869         bRet = !SendMessage16( hWndViewer, WM_CHANGECBCHAIN,
870                              (WPARAM16)hWnd, (LPARAM)hWndNext);   
871     else
872         WARN(clipboard, "hWndViewer is lost\n");
873
874     if( hWnd == hWndViewer ) hWndViewer = hWndNext;
875
876     return bRet;
877 }
878
879
880
881 /**************************************************************************
882  *           IsClipboardFormatAvailable16   (USER.193)
883  */
884 BOOL16 WINAPI IsClipboardFormatAvailable16( UINT16 wFormat )
885 {
886     return IsClipboardFormatAvailable( wFormat );
887 }
888
889
890 /**************************************************************************
891  *           IsClipboardFormatAvailable32   (USER32.340)
892  */
893 BOOL WINAPI IsClipboardFormatAvailable( UINT wFormat )
894 {
895     TRACE(clipboard,"(%04X) !\n", wFormat);
896
897     if( (wFormat == CF_TEXT || wFormat == CF_OEMTEXT) )
898         CLIPBOARD_GetDriver()->pRequestSelection();
899
900     return CLIPBOARD_IsPresent(wFormat);
901 }
902
903
904 /**************************************************************************
905  *             GetOpenClipboardWindow16   (USER.248)
906  */
907 HWND16 WINAPI GetOpenClipboardWindow16(void)
908 {
909     return hWndClipWindow;
910 }
911
912
913 /**************************************************************************
914  *             GetOpenClipboardWindow32   (USER32.277)
915  */
916 HWND WINAPI GetOpenClipboardWindow(void)
917 {
918     return hWndClipWindow;
919 }
920
921
922 /**************************************************************************
923  *             GetPriorityClipboardFormat16   (USER.402)
924  */
925 INT16 WINAPI GetPriorityClipboardFormat16( UINT16 *lpPriorityList, INT16 nCount)
926 {
927     FIXME(clipboard, "(%p,%d): stub\n", lpPriorityList, nCount );
928     return 0;
929 }
930
931
932 /**************************************************************************
933  *             GetPriorityClipboardFormat32   (USER32.279)
934  */
935 INT WINAPI GetPriorityClipboardFormat( UINT *lpPriorityList, INT nCount )
936 {
937     int Counter;
938
939     if(CountClipboardFormats() == 0) 
940     { 
941         return 0;
942     }
943
944     for(Counter = 0; Counter <= nCount; Counter++)
945     {
946         if(IsClipboardFormatAvailable(*(lpPriorityList+sizeof(INT)*Counter)))
947             return *(lpPriorityList+sizeof(INT)*Counter);
948     }
949
950     return -1;
951 }
952
953
954