- Make MTA dynamically allocated so that proxies and other resources
[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 "user_private.h"
52 #include "win.h"
53
54 #include "wine/debug.h"
55 #include "wine/unicode.h"
56 #include "wine/server.h"
57
58 WINE_DEFAULT_DEBUG_CHANNEL(clipboard);
59
60 #define  CF_REGFORMATBASE       0xC000
61
62 typedef struct
63 {
64     HWND hWndOpen;
65     HWND hWndOwner;
66     HWND hWndViewer;
67     UINT seqno;
68     UINT flags;
69 } CLIPBOARDINFO, *LPCLIPBOARDINFO;
70
71 /*
72  * Indicates if data has changed since open.
73  */
74 static BOOL bCBHasChanged = FALSE;
75
76
77 /**************************************************************************
78  *                      CLIPBOARD_SetClipboardOwner
79  *
80  * Set the global wineserver clipboard owner. The current process will
81  * be the owner and <hWnd> will get the render notifications.
82  */
83 BOOL CLIPBOARD_SetClipboardOwner(HWND hWnd)
84 {
85     BOOL bRet = FALSE;
86
87     TRACE(" hWnd(%p)\n", hWnd);
88
89     SERVER_START_REQ( set_clipboard_info )
90     {
91         req->flags = SET_CB_OWNER;
92         req->owner = WIN_GetFullHandle( hWnd );
93
94         if (wine_server_call_err( req ))
95         {
96             ERR("Failed to set clipboard owner to %p\n", hWnd);
97         }
98         else
99         {
100             bRet = TRUE;
101         }
102     }
103     SERVER_END_REQ;
104
105     return bRet;
106 }
107
108
109 /**************************************************************************
110  *                      CLIPBOARD_GetClipboardInfo
111  */
112 static BOOL CLIPBOARD_GetClipboardInfo(LPCLIPBOARDINFO cbInfo)
113 {
114     BOOL bRet = FALSE;
115
116     SERVER_START_REQ( set_clipboard_info )
117     {
118         req->flags = 0;
119
120         if (wine_server_call_err( req ))
121         {
122             ERR("Failed to get clipboard info\n");
123         }
124         else
125         {
126             cbInfo->hWndOpen = reply->old_clipboard;
127             cbInfo->hWndOwner = reply->old_owner;
128             cbInfo->hWndViewer = reply->old_viewer;
129             cbInfo->seqno = reply->seqno;
130             cbInfo->flags = reply->flags;
131
132             bRet = TRUE;
133         }
134     }
135     SERVER_END_REQ;
136
137     return bRet;
138 }
139
140
141 /**************************************************************************
142  *      CLIPBOARD_ReleaseOwner
143  */
144 BOOL CLIPBOARD_ReleaseOwner(void)
145 {
146     BOOL bRet = FALSE;
147
148     SERVER_START_REQ( set_clipboard_info )
149     {
150         req->flags = SET_CB_RELOWNER | SET_CB_SEQNO;
151
152         if (wine_server_call_err( req ))
153         {
154             ERR("Failed to set clipboard.\n");
155         }
156         else
157         {
158             bRet = TRUE;
159         }
160     }
161     SERVER_END_REQ;
162
163     return bRet;
164 }
165
166
167 /**************************************************************************
168  *              CLIPBOARD_OpenClipboard
169  */
170 static BOOL CLIPBOARD_OpenClipboard(HWND hWnd)
171 {
172     BOOL bRet = FALSE;
173
174     SERVER_START_REQ( set_clipboard_info )
175     {
176         req->flags = SET_CB_OPEN;
177         req->clipboard = WIN_GetFullHandle( hWnd );
178
179         if (!wine_server_call( req ))
180             bRet = TRUE;
181     }
182     SERVER_END_REQ;
183
184     return bRet;
185 }
186
187
188 /**************************************************************************
189  *              CLIPBOARD_CloseClipboard
190  */
191 static BOOL CLIPBOARD_CloseClipboard(void)
192 {
193     BOOL bRet = FALSE;
194
195     TRACE(" Changed=%d\n", bCBHasChanged);
196
197     SERVER_START_REQ( set_clipboard_info )
198     {
199         req->flags = SET_CB_CLOSE;
200
201         if (bCBHasChanged)
202         {
203             req->flags |= SET_CB_SEQNO;
204             TRACE("Clipboard data changed\n");
205         }
206
207         if (wine_server_call_err( req ))
208         {
209             ERR("Failed to set clipboard.\n");
210         }
211         else
212         {
213             bRet = TRUE;
214         }
215     }
216     SERVER_END_REQ;
217
218     return bRet;
219 }
220
221
222 /**************************************************************************
223  *                WIN32 Clipboard implementation
224  **************************************************************************/
225
226 /**************************************************************************
227  *              RegisterClipboardFormatW (USER32.@)
228  */
229 UINT WINAPI RegisterClipboardFormatW(LPCWSTR FormatName)
230 {
231     UINT wFormatID = 0;
232
233     TRACE("%s\n", debugstr_w(FormatName));
234
235     if (USER_Driver.pRegisterClipboardFormat)
236         wFormatID = USER_Driver.pRegisterClipboardFormat(FormatName);
237
238     return wFormatID;
239 }
240
241
242 /**************************************************************************
243  *              RegisterClipboardFormatA (USER32.@)
244  */
245 UINT WINAPI RegisterClipboardFormatA(LPCSTR formatName)
246 {
247     int len;
248     LPWSTR wFormat;
249     UINT ret;
250
251     len = MultiByteToWideChar(CP_ACP, 0, formatName, -1, NULL, 0);
252     wFormat = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
253     MultiByteToWideChar(CP_ACP, 0, formatName, -1, wFormat, len);
254
255     ret = RegisterClipboardFormatW(wFormat);
256     HeapFree(GetProcessHeap(), 0, wFormat);
257     return ret;
258 }
259
260
261 /**************************************************************************
262  *              GetClipboardFormatNameW (USER32.@)
263  */
264 INT WINAPI GetClipboardFormatNameW(UINT wFormat, LPWSTR retStr, INT maxlen)
265 {
266     INT len = 0;
267
268     TRACE("%04x,%p,%d\n", wFormat, retStr, maxlen);
269
270     if (USER_Driver.pGetClipboardFormatName)
271         len = USER_Driver.pGetClipboardFormatName(wFormat, retStr, maxlen);
272
273     return len;
274 }
275
276
277 /**************************************************************************
278  *              GetClipboardFormatNameA (USER32.@)
279  */
280 INT WINAPI GetClipboardFormatNameA(UINT wFormat, LPSTR retStr, INT maxlen)
281 {
282     INT ret;
283     LPWSTR p = HeapAlloc( GetProcessHeap(), 0, maxlen*sizeof(WCHAR) );
284     if(p == NULL) return 0; /* FIXME: is this the correct failure value? */
285
286     ret = GetClipboardFormatNameW( wFormat, p, maxlen );
287
288     if (maxlen > 0 && !WideCharToMultiByte( CP_ACP, 0, p, -1, retStr, maxlen, 0, 0))
289         retStr[maxlen-1] = 0;
290     HeapFree( GetProcessHeap(), 0, p );
291     return ret;
292 }
293
294
295 /**************************************************************************
296  *              OpenClipboard (USER32.@)
297  *
298  * Note: Netscape uses NULL hWnd to open the clipboard.
299  */
300 BOOL WINAPI OpenClipboard( HWND hWnd )
301 {
302     BOOL bRet;
303
304     TRACE("(%p)...\n", hWnd);
305
306     bRet = CLIPBOARD_OpenClipboard(hWnd);
307
308     TRACE(" returning %i\n", bRet);
309
310     return bRet;
311 }
312
313
314 /**************************************************************************
315  *              CloseClipboard (USER32.@)
316  */
317 BOOL WINAPI CloseClipboard(void)
318 {
319     BOOL bRet = FALSE;
320
321     TRACE("(%d)\n", bCBHasChanged);
322
323     if (CLIPBOARD_CloseClipboard())
324     {
325         if (bCBHasChanged)
326         {
327             HWND hWndViewer = GetClipboardViewer();
328
329             if (USER_Driver.pEndClipboardUpdate)
330                 USER_Driver.pEndClipboardUpdate();
331  
332             if (hWndViewer)
333                 SendMessageW(hWndViewer, WM_DRAWCLIPBOARD, 0, 0);
334  
335             bCBHasChanged = FALSE;
336         }
337
338         bRet = TRUE;
339     }
340
341     return bRet;
342 }
343
344
345 /**************************************************************************
346  *              EmptyClipboard (USER32.@)
347  * Empties and acquires ownership of the clipboard
348  */
349 BOOL WINAPI EmptyClipboard(void)
350 {
351     CLIPBOARDINFO cbinfo;
352  
353     TRACE("()\n");
354
355     if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
356         ~cbinfo.flags & CB_OPEN)
357     { 
358         WARN("Clipboard not opened by calling task!\n");
359         SetLastError(ERROR_CLIPBOARD_NOT_OPEN);
360         return FALSE;
361     }
362
363     /* Destroy private objects */
364     if (cbinfo.hWndOwner) 
365         SendMessageW(cbinfo.hWndOwner, WM_DESTROYCLIPBOARD, 0, 0);
366
367     /* Tell the driver to acquire the selection. The current owner
368      * will be signaled to delete it's own cache. */
369
370     /* Assign ownership of the clipboard to the current client. We do
371      * this before acquiring the selection so that when we do acquire the
372      * selection and the selection loser gets notified, it can check if 
373      * it has lost the Wine clipboard ownership. If it did then it knows
374      * that a WM_DESTORYCLIPBOARD has already been sent. Otherwise it
375      * lost the selection to a X app and it should send the 
376      * WM_DESTROYCLIPBOARD itself. */
377     CLIPBOARD_SetClipboardOwner(cbinfo.hWndOpen);
378
379     /* Acquire the selection. This will notify the previous owner
380      * to clear it's cache. */ 
381     if (USER_Driver.pAcquireClipboard) 
382         USER_Driver.pAcquireClipboard(cbinfo.hWndOpen);
383
384     /* Empty the local cache */
385     if (USER_Driver.pEmptyClipboard) 
386         USER_Driver.pEmptyClipboard(FALSE);
387  
388     bCBHasChanged = TRUE;
389
390     return TRUE;
391 }
392
393
394 /**************************************************************************
395  *              GetClipboardOwner (USER32.@)
396  *  FIXME: Can't return the owner if the clipboard is owned by an external X-app
397  */
398 HWND WINAPI GetClipboardOwner(void)
399 {
400     HWND hWndOwner = 0;
401
402     SERVER_START_REQ( set_clipboard_info )
403     {
404         req->flags = 0;
405         if (!wine_server_call_err( req )) hWndOwner = reply->old_owner;
406     }
407     SERVER_END_REQ;
408
409     TRACE(" hWndOwner(%p)\n", hWndOwner);
410
411     return hWndOwner;
412 }
413
414
415 /**************************************************************************
416  *              GetOpenClipboardWindow (USER32.@)
417  */
418 HWND WINAPI GetOpenClipboardWindow(void)
419 {
420     HWND hWndOpen = 0;
421
422     SERVER_START_REQ( set_clipboard_info )
423     {
424         req->flags = 0;
425         if (!wine_server_call_err( req )) hWndOpen = reply->old_clipboard;
426     }
427     SERVER_END_REQ;
428
429     TRACE(" hWndClipWindow(%p)\n", hWndOpen);
430
431     return hWndOpen;
432 }
433
434
435 /**************************************************************************
436  *              SetClipboardViewer (USER32.@)
437  */
438 HWND WINAPI SetClipboardViewer( HWND hWnd )
439 {
440     HWND hwndPrev = 0;
441  
442     SERVER_START_REQ( set_clipboard_info )
443     {
444         req->flags = SET_CB_VIEWER;
445         req->viewer = WIN_GetFullHandle(hWnd);
446  
447         if (wine_server_call_err( req ))
448         {
449             ERR("Failed to set clipboard.\n");
450         }
451         else
452         {
453             hwndPrev = reply->old_viewer;
454         }
455     }
456     SERVER_END_REQ;
457  
458     TRACE("(%p): returning %p\n", hWnd, hwndPrev);
459   
460     return hwndPrev;
461 }
462
463
464 /**************************************************************************
465  *              GetClipboardViewer (USER32.@)
466  */
467 HWND WINAPI GetClipboardViewer(void)
468 {
469     HWND hWndViewer = 0;
470
471     SERVER_START_REQ( set_clipboard_info )
472     {
473         req->flags = 0;
474         if (!wine_server_call_err( req )) hWndViewer = reply->old_viewer;
475     }
476     SERVER_END_REQ;
477
478     TRACE(" hWndViewer=%p\n", hWndViewer);
479
480     return hWndViewer;
481 }
482
483
484 /**************************************************************************
485  *              ChangeClipboardChain (USER32.@)
486  */
487 BOOL WINAPI ChangeClipboardChain(HWND hWnd, HWND hWndNext)
488 {
489     BOOL bRet = TRUE;
490     HWND hWndViewer = GetClipboardViewer();
491
492     if (hWndViewer)
493     {
494         if (WIN_GetFullHandle(hWnd) == hWndViewer) 
495             SetClipboardViewer(WIN_GetFullHandle(hWndNext));
496         else
497             bRet = !SendMessageW(hWndViewer, WM_CHANGECBCHAIN, (WPARAM)hWnd, (LPARAM)hWndNext);
498     }
499     else
500         ERR("hWndViewer is lost\n");
501
502     return bRet;
503 }
504
505
506 /**************************************************************************
507  *              SetClipboardData (USER.141)
508  */
509 HANDLE16 WINAPI SetClipboardData16(UINT16 wFormat, HANDLE16 hData)
510 {
511     CLIPBOARDINFO cbinfo;
512     HANDLE16 hResult = 0;
513
514     TRACE("(%04X, %04x) !\n", wFormat, hData);
515
516     /* If it's not owned, data can only be set if the format doesn't exists
517        and its rendering is not delayed */
518     if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
519         (!(cbinfo.flags & CB_OWNER) && !hData))
520     {
521         WARN("Clipboard not owned by calling task. Operation failed.\n");
522         return 0;
523     }
524
525     if (USER_Driver.pSetClipboardData &&
526         USER_Driver.pSetClipboardData(wFormat, hData, 0, cbinfo.flags & CB_OWNER))
527     {
528         hResult = hData;
529         bCBHasChanged = TRUE;
530     }
531
532     return hResult;
533 }
534
535
536 /**************************************************************************
537  *              SetClipboardData (USER32.@)
538  */
539 HANDLE WINAPI SetClipboardData(UINT wFormat, HANDLE hData)
540 {
541     CLIPBOARDINFO cbinfo;
542     HANDLE hResult = 0;
543
544     TRACE("(%04X, %p) !\n", wFormat, hData);
545
546     /* If it's not owned, data can only be set if the format isn't
547        available and its rendering is not delayed */
548     if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
549        (!(cbinfo.flags & CB_OWNER) && !hData))
550     {
551         WARN("Clipboard not owned by calling task. Operation failed.\n");
552         return 0;
553     }
554
555     if (USER_Driver.pSetClipboardData &&
556         USER_Driver.pSetClipboardData(wFormat, 0, hData, cbinfo.flags & CB_OWNER))
557     {
558         hResult = hData;
559         bCBHasChanged = TRUE;
560     }
561
562     return hResult;
563 }
564
565
566 /**************************************************************************
567  *              CountClipboardFormats (USER32.@)
568  */
569 INT WINAPI CountClipboardFormats(void)
570 {
571     INT count = 0;
572
573     if (USER_Driver.pCountClipboardFormats)
574         count = USER_Driver.pCountClipboardFormats();
575
576     TRACE("returning %d\n", count);
577     return count;
578 }
579
580
581 /**************************************************************************
582  *              EnumClipboardFormats (USER32.@)
583  */
584 UINT WINAPI EnumClipboardFormats(UINT wFormat)
585 {
586     UINT wFmt = 0;
587     CLIPBOARDINFO cbinfo;
588
589     TRACE("(%04X)\n", wFormat);
590
591     if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
592         (~cbinfo.flags & CB_OPEN))
593     {
594         WARN("Clipboard not opened by calling task.\n");
595         SetLastError(ERROR_CLIPBOARD_NOT_OPEN);
596         return 0;
597     }
598
599     if (USER_Driver.pEnumClipboardFormats)
600         wFmt = USER_Driver.pEnumClipboardFormats(wFormat);
601
602     return wFmt;
603 }
604
605
606 /**************************************************************************
607  *              IsClipboardFormatAvailable (USER32.@)
608  */
609 BOOL WINAPI IsClipboardFormatAvailable(UINT wFormat)
610 {
611     BOOL bret = FALSE;
612
613     if (USER_Driver.pIsClipboardFormatAvailable)
614         bret = USER_Driver.pIsClipboardFormatAvailable(wFormat);
615
616     TRACE("%04x, returning %d\n", wFormat, bret);
617     return bret;
618 }
619
620
621 /**************************************************************************
622  *              GetClipboardData (USER.142)
623  */
624 HANDLE16 WINAPI GetClipboardData16(UINT16 wFormat)
625 {
626     HANDLE16 hData = 0;
627     CLIPBOARDINFO cbinfo;
628
629     if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
630         (~cbinfo.flags & CB_OPEN))
631     {
632         WARN("Clipboard not opened by calling task.\n");
633         SetLastError(ERROR_CLIPBOARD_NOT_OPEN);
634         return 0;
635     }
636
637     if (USER_Driver.pGetClipboardData)
638         USER_Driver.pGetClipboardData(wFormat, &hData, NULL);
639
640     return hData;
641 }
642
643
644 /**************************************************************************
645  *              GetClipboardData (USER32.@)
646  */
647 HANDLE WINAPI GetClipboardData(UINT wFormat)
648 {
649     HANDLE hData = 0;
650     CLIPBOARDINFO cbinfo;
651
652     TRACE("%04x\n", wFormat);
653
654     if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
655         (~cbinfo.flags & CB_OPEN))
656     {
657         WARN("Clipboard not opened by calling task.\n");
658         SetLastError(ERROR_CLIPBOARD_NOT_OPEN);
659         return 0;
660     }
661
662     if (USER_Driver.pGetClipboardData)
663         USER_Driver.pGetClipboardData(wFormat, NULL, &hData);
664
665     TRACE("returning %p\n", hData);
666     return hData;
667 }
668
669
670 /**************************************************************************
671  *              GetPriorityClipboardFormat (USER32.@)
672  */
673 INT WINAPI GetPriorityClipboardFormat(UINT *list, INT nCount)
674 {
675     int i;
676
677     TRACE("()\n");
678
679     if(CountClipboardFormats() == 0)
680         return 0;
681
682     for (i = 0; i < nCount; i++)
683         if (IsClipboardFormatAvailable(list[i]))
684             return list[i];
685
686     return -1;
687 }
688
689
690 /**************************************************************************
691  *              GetClipboardSequenceNumber (USER32.@)
692  * Supported on Win2k/Win98
693  * MSDN: Windows clipboard code keeps a serial number for the clipboard
694  * for each window station.  The number is incremented whenever the
695  * contents change or are emptied.
696  * If you do not have WINSTA_ACCESSCLIPBOARD then the function returns 0
697  */
698 DWORD WINAPI GetClipboardSequenceNumber(VOID)
699 {
700     DWORD seqno = 0;
701
702     SERVER_START_REQ( set_clipboard_info )
703     {
704         req->flags = 0;
705         if (!wine_server_call_err( req )) seqno = reply->seqno;
706     }
707     SERVER_END_REQ;
708
709     TRACE("returning %lx\n", seqno);
710     return seqno;
711 }