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