Make DestroyWindow() not mess with a window focus, this should be
[wine] / windows / clipboard.c
1 /*
2  * WIN32 clipboard implementation
3  *
4  * Copyright 1994 Martin Ayotte
5  *           1996 Alex Korobka
6  *           1999 Noel Borthwick
7  *           2003 Ulrich Czekalla for CodeWeavers
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  *
23  * NOTES:
24  *    This file contains the implementation for the WIN32 Clipboard API
25  * and Wine's internal clipboard cache.
26  * The actual contents of the clipboard are held in the clipboard cache.
27  * The internal implementation talks to a "clipboard driver" to fill or
28  * expose the cache to the native device. (Currently only the X11 and
29  * TTY clipboard  driver are available)
30  */
31
32 #include "config.h"
33 #include "wine/port.h"
34
35 #include <stdarg.h>
36 #include <stdlib.h>
37 #include <sys/types.h>
38 #include <fcntl.h>
39 #ifdef HAVE_UNISTD_H
40 # include <unistd.h>
41 #endif
42 #include <string.h>
43
44 #include "windef.h"
45 #include "winbase.h"
46 #include "wingdi.h"
47 #include "winuser.h"
48 #include "winerror.h"
49 #include "wine/winuser16.h"
50 #include "wine/winbase16.h"
51 #include "heap.h"
52 #include "user.h"
53 #include "win.h"
54
55 #include "wine/debug.h"
56 #include "wine/unicode.h"
57 #include "wine/server.h"
58
59 WINE_DEFAULT_DEBUG_CHANNEL(clipboard);
60
61 #define  CF_REGFORMATBASE       0xC000
62
63 typedef struct
64 {
65     HWND hWndOpen;
66     HWND hWndOwner;
67     HWND hWndViewer;
68     UINT seqno;
69     UINT flags;
70 } CLIPBOARDINFO, *LPCLIPBOARDINFO;
71
72 /*
73  * Indicates if data has changed since open.
74  */
75 static BOOL bCBHasChanged = FALSE;
76
77
78 /**************************************************************************
79  *                      CLIPBOARD_SetClipboardOwner
80  */
81 BOOL CLIPBOARD_SetClipboardOwner(HWND hWnd)
82 {
83     BOOL bRet = FALSE;
84
85     TRACE(" hWnd(%p)\n", hWnd);
86
87     SERVER_START_REQ( set_clipboard_info )
88     {
89         req->flags = SET_CB_OWNER;
90         req->owner = WIN_GetFullHandle( hWnd );
91
92         if (wine_server_call_err( req ))
93         {
94             ERR("Failed to set clipboard.\n");
95         }
96         else
97         {
98             bRet = TRUE;
99         }
100     }
101     SERVER_END_REQ;
102
103     return bRet;
104 }
105
106
107 /**************************************************************************
108  *                      CLIPBOARD_GetClipboardInfo
109  */
110 static BOOL CLIPBOARD_GetClipboardInfo(LPCLIPBOARDINFO cbInfo)
111 {
112     BOOL bRet = FALSE;
113
114     SERVER_START_REQ( set_clipboard_info )
115     {
116         req->flags = 0;
117
118         if (wine_server_call_err( req ))
119         {
120             ERR("Failed to get clipboard owner.\n");
121         }
122         else
123         {
124             cbInfo->hWndOpen = reply->old_clipboard;
125             cbInfo->hWndOwner = reply->old_owner;
126             cbInfo->hWndViewer = reply->old_viewer;
127             cbInfo->seqno = reply->seqno;
128             cbInfo->flags = reply->flags;
129
130             bRet = TRUE;
131         }
132     }
133     SERVER_END_REQ;
134
135     return bRet;
136 }
137
138
139 /**************************************************************************
140  *      CLIPBOARD_ReleaseOwner
141  */
142 BOOL CLIPBOARD_ReleaseOwner(void)
143 {
144     BOOL bRet = FALSE;
145
146     SERVER_START_REQ( set_clipboard_info )
147     {
148         req->flags = SET_CB_RELOWNER | SET_CB_SEQNO;
149
150         if (wine_server_call_err( req ))
151         {
152             ERR("Failed to set clipboard.\n");
153         }
154         else
155         {
156             bRet = TRUE;
157         }
158     }
159     SERVER_END_REQ;
160
161     return bRet;
162 }
163
164
165 /**************************************************************************
166  *              CLIPBOARD_OpenClipboard
167  */
168 static BOOL CLIPBOARD_OpenClipboard(HWND hWnd)
169 {
170     BOOL bRet = FALSE;
171
172     SERVER_START_REQ( set_clipboard_info )
173     {
174         req->flags = SET_CB_OPEN;
175         req->clipboard = WIN_GetFullHandle( hWnd );
176
177         if (wine_server_call_err( req ))
178         {
179             ERR("Failed to set clipboard.\n");
180         }
181         else
182         {
183             bRet = TRUE;
184         }
185     }
186     SERVER_END_REQ;
187
188     return bRet;
189 }
190
191
192 /**************************************************************************
193  *              CLIPBOARD_CloseClipboard
194  */
195 static BOOL CLIPBOARD_CloseClipboard(void)
196 {
197     BOOL bRet = FALSE;
198
199     TRACE(" Changed=%d\n", bCBHasChanged);
200
201     SERVER_START_REQ( set_clipboard_info )
202     {
203         req->flags = SET_CB_CLOSE;
204
205         if (bCBHasChanged)
206         {
207             req->flags |= SET_CB_SEQNO;
208             TRACE("Clipboard data changed\n");
209         }
210
211         if (wine_server_call_err( req ))
212         {
213             ERR("Failed to set clipboard.\n");
214         }
215         else
216         {
217             bRet = TRUE;
218         }
219     }
220     SERVER_END_REQ;
221
222     return bRet;
223 }
224
225
226 /**************************************************************************
227  *                WIN32 Clipboard implementation
228  **************************************************************************/
229
230 /**************************************************************************
231  *              RegisterClipboardFormatA (USER32.@)
232  */
233 UINT WINAPI RegisterClipboardFormatA(LPCSTR FormatName)
234 {
235     UINT wFormatID = 0;
236
237     TRACE("%s\n", debugstr_a(FormatName));
238
239     if (USER_Driver.pRegisterClipboardFormat)
240         wFormatID = USER_Driver.pRegisterClipboardFormat(FormatName);
241
242     return wFormatID;
243 }
244
245
246 /**************************************************************************
247  *              RegisterClipboardFormat (USER.145)
248  */
249 UINT16 WINAPI RegisterClipboardFormat16(LPCSTR FormatName)
250 {
251     UINT wFormatID = 0;
252
253     TRACE("%s\n", debugstr_a(FormatName));
254
255     if (USER_Driver.pRegisterClipboardFormat)
256         wFormatID = USER_Driver.pRegisterClipboardFormat(FormatName);
257
258     return wFormatID;
259 }
260
261
262 /**************************************************************************
263  *              RegisterClipboardFormatW (USER32.@)
264  */
265 UINT WINAPI RegisterClipboardFormatW(LPCWSTR formatName)
266 {
267     LPSTR aFormat = HEAP_strdupWtoA( GetProcessHeap(), 0, formatName );
268     UINT ret = RegisterClipboardFormatA( aFormat );
269     HeapFree( GetProcessHeap(), 0, aFormat );
270     return ret;
271 }
272
273
274 /**************************************************************************
275  *              GetClipboardFormatName (USER.146)
276  */
277 INT16 WINAPI GetClipboardFormatName16(UINT16 wFormat, LPSTR retStr, INT16 maxlen)
278 {
279     TRACE("%04x,%p,%d\n", wFormat, retStr, maxlen);
280
281     return GetClipboardFormatNameA(wFormat, retStr, maxlen);
282 }
283
284
285 /**************************************************************************
286  *              GetClipboardFormatNameA (USER32.@)
287  */
288 INT WINAPI GetClipboardFormatNameA(UINT wFormat, LPSTR retStr, INT maxlen)
289 {
290     INT len = 0;
291
292     TRACE("%04x,%p,%d\n", wFormat, retStr, maxlen);
293
294     if (USER_Driver.pGetClipboardFormatName)
295         len = USER_Driver.pGetClipboardFormatName(wFormat, retStr, maxlen);
296
297     return len;
298 }
299
300
301 /**************************************************************************
302  *              GetClipboardFormatNameW (USER32.@)
303  */
304 INT WINAPI GetClipboardFormatNameW(UINT wFormat, LPWSTR retStr, INT maxlen)
305 {
306     INT ret;
307     LPSTR p = HeapAlloc( GetProcessHeap(), 0, maxlen );
308     if(p == NULL) return 0; /* FIXME: is this the correct failure value? */
309
310     ret = GetClipboardFormatNameA( wFormat, p, maxlen );
311
312     if (maxlen > 0 && !MultiByteToWideChar( CP_ACP, 0, p, -1, retStr, maxlen ))
313         retStr[maxlen-1] = 0;
314     HeapFree( GetProcessHeap(), 0, p );
315     return ret;
316 }
317
318
319 /**************************************************************************
320  *              OpenClipboard (USER32.@)
321  *
322  * Note: Netscape uses NULL hWnd to open the clipboard.
323  */
324 BOOL WINAPI OpenClipboard( HWND hWnd )
325 {
326     BOOL bRet;
327
328     TRACE("(%p)...\n", hWnd);
329
330     bRet = CLIPBOARD_OpenClipboard(hWnd);
331
332     TRACE(" returning %i\n", bRet);
333
334     return bRet;
335 }
336
337
338 /**************************************************************************
339  *              CloseClipboard (USER.138)
340  */
341 BOOL16 WINAPI CloseClipboard16(void)
342 {
343     return CloseClipboard();
344 }
345
346
347 /**************************************************************************
348  *              CloseClipboard (USER32.@)
349  */
350 BOOL WINAPI CloseClipboard(void)
351 {
352     BOOL bRet = FALSE;
353
354     TRACE("(%d)\n", bCBHasChanged);
355
356     if (CLIPBOARD_CloseClipboard())
357     {
358         if (bCBHasChanged)
359         {
360             HWND hWndViewer = GetClipboardViewer();
361
362             if (USER_Driver.pEndClipboardUpdate)
363                 USER_Driver.pEndClipboardUpdate();
364  
365             if (hWndViewer)
366                 SendMessageW(hWndViewer, WM_DRAWCLIPBOARD, 0, 0);
367  
368             bCBHasChanged = FALSE;
369         }
370
371         bRet = TRUE;
372     }
373
374     return bRet;
375 }
376
377
378 /**************************************************************************
379  *              EmptyClipboard (USER.139)
380  */
381 BOOL16 WINAPI EmptyClipboard16(void)
382 {
383     return EmptyClipboard();
384 }
385
386
387 /**************************************************************************
388  *              EmptyClipboard (USER32.@)
389  * Empties and acquires ownership of the clipboard
390  */
391 BOOL WINAPI EmptyClipboard(void)
392 {
393     CLIPBOARDINFO cbinfo;
394  
395     TRACE("()\n");
396
397     if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
398         ~cbinfo.flags & CB_OPEN)
399     { 
400         WARN("Clipboard not opened by calling task!\n");
401         SetLastError(ERROR_CLIPBOARD_NOT_OPEN);
402         return FALSE;
403     }
404
405     /* Destroy private objects */
406     if (cbinfo.hWndOwner) 
407         SendMessageW(cbinfo.hWndOwner, WM_DESTROYCLIPBOARD, 0, 0);
408
409     /* Tell the driver to acquire the selection. The current owner
410      * will be signaled to delete it's own cache. */
411     if (~cbinfo.flags & CB_OWNER)
412     {
413         /* Assign ownership of the clipboard to the current client. We do
414          * this before acquiring the selection so that when we do acquire the
415          * selection and the selection loser gets notified, it can check if 
416          * it has lost the Wine clipboard ownership. If it did then it knows
417          * that a WM_DESTORYCLIPBOARD has already been sent. Otherwise it
418          * lost the selection to a X app and it should send the 
419          * WM_DESTROYCLIPBOARD itself. */
420         CLIPBOARD_SetClipboardOwner(cbinfo.hWndOpen);
421
422         /* Acquire the selection. This will notify the previous owner
423          * to clear it's cache. */ 
424         if (USER_Driver.pAcquireClipboard) 
425             USER_Driver.pAcquireClipboard(cbinfo.hWndOpen);
426     }
427
428     /* Empty the local cache */
429     if (USER_Driver.pEmptyClipboard) 
430         USER_Driver.pEmptyClipboard();
431  
432     bCBHasChanged = TRUE;
433
434     return TRUE;
435 }
436
437
438 /**************************************************************************
439  *              GetClipboardOwner (USER32.@)
440  *  FIXME: Can't return the owner if the clipboard is owned by an external X-app
441  */
442 HWND WINAPI GetClipboardOwner(void)
443 {
444     HWND hWndOwner = 0;
445
446     SERVER_START_REQ( set_clipboard_info )
447     {
448         req->flags = 0;
449         if (!wine_server_call_err( req )) hWndOwner = reply->old_owner;
450     }
451     SERVER_END_REQ;
452
453     TRACE(" hWndOwner(%p)\n", hWndOwner);
454
455     return hWndOwner;
456 }
457
458
459 /**************************************************************************
460  *              GetOpenClipboardWindow (USER32.@)
461  */
462 HWND WINAPI GetOpenClipboardWindow(void)
463 {
464     HWND hWndOpen = 0;
465
466     SERVER_START_REQ( set_clipboard_info )
467     {
468         req->flags = 0;
469         if (!wine_server_call_err( req )) hWndOpen = reply->old_clipboard;
470     }
471     SERVER_END_REQ;
472
473     TRACE(" hWndClipWindow(%p)\n", hWndOpen);
474
475     return hWndOpen;
476 }
477
478
479 /**************************************************************************
480  *              SetClipboardViewer (USER32.@)
481  */
482 HWND WINAPI SetClipboardViewer( HWND hWnd )
483 {
484     HWND hwndPrev = 0;
485  
486     SERVER_START_REQ( set_clipboard_info )
487     {
488         req->flags = SET_CB_VIEWER;
489         req->viewer = WIN_GetFullHandle(hWnd);
490  
491         if (wine_server_call_err( req ))
492         {
493             ERR("Failed to set clipboard.\n");
494         }
495         else
496         {
497             hwndPrev = reply->old_viewer;
498         }
499     }
500     SERVER_END_REQ;
501  
502     TRACE("(%p): returning %p\n", hWnd, hwndPrev);
503   
504     return hwndPrev;
505 }
506
507
508 /**************************************************************************
509  *              GetClipboardViewer (USER32.@)
510  */
511 HWND WINAPI GetClipboardViewer(void)
512 {
513     HWND hWndViewer = 0;
514
515     SERVER_START_REQ( set_clipboard_info )
516     {
517         req->flags = 0;
518         if (!wine_server_call_err( req )) hWndViewer = reply->old_viewer;
519     }
520     SERVER_END_REQ;
521
522     TRACE(" hWndViewer=%p\n", hWndViewer);
523
524     return hWndViewer;
525 }
526
527
528 /**************************************************************************
529  *              ChangeClipboardChain (USER32.@)
530  */
531 BOOL WINAPI ChangeClipboardChain(HWND hWnd, HWND hWndNext)
532 {
533     BOOL bRet = TRUE;
534     HWND hWndViewer = GetClipboardViewer();
535
536     if (hWndViewer)
537     {
538         if (WIN_GetFullHandle(hWnd) == hWndViewer) 
539             SetClipboardViewer(WIN_GetFullHandle(hWndNext));
540         else
541             bRet = !SendMessageW(hWndViewer, WM_CHANGECBCHAIN, (WPARAM)hWnd, (LPARAM)hWndNext);
542     }
543     else
544         ERR("hWndViewer is lost\n");
545
546     return bRet;
547 }
548
549
550 /**************************************************************************
551  *              SetClipboardData (USER.141)
552  */
553 HANDLE16 WINAPI SetClipboardData16(UINT16 wFormat, HANDLE16 hData)
554 {
555     CLIPBOARDINFO cbinfo;
556     HANDLE16 hResult = 0;
557
558     TRACE("(%04X, %04x) !\n", wFormat, hData);
559
560     if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
561         (~cbinfo.flags & CB_OPEN) ||
562         (~cbinfo.flags & CB_OWNER))
563     {
564         WARN("Clipboard not opened by calling task!\n");
565     }
566     else if (USER_Driver.pSetClipboardData &&
567         USER_Driver.pSetClipboardData(wFormat, hData, 0))
568     {
569         hResult = hData;
570         bCBHasChanged = TRUE;
571     }
572
573     return hResult;
574 }
575
576
577 /**************************************************************************
578  *              SetClipboardData (USER32.@)
579  */
580 HANDLE WINAPI SetClipboardData(UINT wFormat, HANDLE hData)
581 {
582     CLIPBOARDINFO cbinfo;
583     HANDLE hResult = 0;
584
585     TRACE("(%04X, %p) !\n", wFormat, hData);
586
587     if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
588         (~cbinfo.flags & CB_OWNER))
589     {
590         WARN("Clipboard not owned by calling task!\n");
591     }
592     else if (USER_Driver.pSetClipboardData &&
593         USER_Driver.pSetClipboardData(wFormat, 0, hData))
594     {
595         hResult = hData;
596         bCBHasChanged = TRUE;
597     }
598
599     return hResult;
600 }
601
602
603 /**************************************************************************
604  *              CountClipboardFormats (USER.143)
605  */
606 INT16 WINAPI CountClipboardFormats16(void)
607 {
608     return CountClipboardFormats();
609 }
610
611
612 /**************************************************************************
613  *              CountClipboardFormats (USER32.@)
614  */
615 INT WINAPI CountClipboardFormats(void)
616 {
617     INT count = 0;
618
619     if (USER_Driver.pCountClipboardFormats)
620         count = USER_Driver.pCountClipboardFormats();
621
622     TRACE("returning %d\n", count);
623     return count;
624 }
625
626
627 /**************************************************************************
628  *              EnumClipboardFormats (USER.144)
629  */
630 UINT16 WINAPI EnumClipboardFormats16(UINT16 wFormat)
631 {
632     return EnumClipboardFormats(wFormat);
633 }
634
635
636 /**************************************************************************
637  *              EnumClipboardFormats (USER32.@)
638  */
639 UINT WINAPI EnumClipboardFormats(UINT wFormat)
640 {
641     UINT wFmt = 0;
642     CLIPBOARDINFO cbinfo;
643
644     TRACE("(%04X)\n", wFormat);
645
646     if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
647         (~cbinfo.flags & CB_OPEN))
648     {
649         WARN("Clipboard not opened by calling task.\n");
650         SetLastError(ERROR_CLIPBOARD_NOT_OPEN);
651         return 0;
652     }
653
654     if (USER_Driver.pEnumClipboardFormats)
655         wFmt = USER_Driver.pEnumClipboardFormats(wFormat);
656
657     return wFmt;
658 }
659
660
661 /**************************************************************************
662  *              IsClipboardFormatAvailable (USER.193)
663  */
664 BOOL16 WINAPI IsClipboardFormatAvailable16(UINT16 wFormat)
665 {
666     return IsClipboardFormatAvailable(wFormat);
667 }
668
669
670 /**************************************************************************
671  *              IsClipboardFormatAvailable (USER32.@)
672  */
673 BOOL WINAPI IsClipboardFormatAvailable(UINT wFormat)
674 {
675     BOOL bret = FALSE;
676
677     if (USER_Driver.pIsClipboardFormatAvailable)
678         bret = USER_Driver.pIsClipboardFormatAvailable(wFormat);
679
680     TRACE("%04x, returning %d\n", wFormat, bret);
681     return bret;
682 }
683
684
685 /**************************************************************************
686  *              GetClipboardData (USER.142)
687  */
688 HANDLE16 WINAPI GetClipboardData16(UINT16 wFormat)
689 {
690     HANDLE16 hData = 0;
691     CLIPBOARDINFO cbinfo;
692
693     if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
694         (~cbinfo.flags & CB_OPEN))
695     {
696         WARN("Clipboard not opened by calling task.\n");
697         SetLastError(ERROR_CLIPBOARD_NOT_OPEN);
698         return 0;
699     }
700
701     if (USER_Driver.pGetClipboardData)
702         USER_Driver.pGetClipboardData(wFormat, &hData, NULL);
703
704     return hData;
705 }
706
707
708 /**************************************************************************
709  *              GetClipboardData (USER32.@)
710  */
711 HANDLE WINAPI GetClipboardData(UINT wFormat)
712 {
713     HANDLE hData = 0;
714     CLIPBOARDINFO cbinfo;
715
716     TRACE("%04x\n", wFormat);
717
718     if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
719         (~cbinfo.flags & CB_OPEN))
720     {
721         WARN("Clipboard not opened by calling task.\n");
722         SetLastError(ERROR_CLIPBOARD_NOT_OPEN);
723         return 0;
724     }
725
726     if (USER_Driver.pGetClipboardData)
727         USER_Driver.pGetClipboardData(wFormat, NULL, &hData);
728
729     TRACE("returning %p\n", hData);
730     return hData;
731 }
732
733
734 /**************************************************************************
735  *              GetPriorityClipboardFormat (USER32.@)
736  */
737 INT WINAPI GetPriorityClipboardFormat(UINT *list, INT nCount)
738 {
739     int i;
740
741     TRACE("()\n");
742
743     if(CountClipboardFormats() == 0)
744         return 0;
745
746     for (i = 0; i < nCount; i++)
747         if (IsClipboardFormatAvailable(list[i]))
748             return list[i];
749
750     return -1;
751 }
752
753
754 /**************************************************************************
755  *              GetClipboardSequenceNumber (USER32.@)
756  * Supported on Win2k/Win98
757  * MSDN: Windows clipboard code keeps a serial number for the clipboard
758  * for each window station.  The number is incremented whenever the
759  * contents change or are emptied.
760  * If you do not have WINSTA_ACCESSCLIPBOARD then the function returns 0
761  */
762 DWORD WINAPI GetClipboardSequenceNumber(VOID)
763 {
764     DWORD seqno = 0;
765
766     SERVER_START_REQ( set_clipboard_info )
767     {
768         req->flags = 0;
769         if (!wine_server_call_err( req )) seqno = reply->seqno;
770     }
771     SERVER_END_REQ;
772
773     TRACE("returning %lx\n", seqno);
774     return seqno;
775 }