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