Return a true boolean value (0 or 1).
[wine/wine64.git] / windows / clipboard.c
bloba5d1431ca4dc537ba16f5a6a8cb6139810a88e79
1 /*
2 * WIN32 clipboard implementation
4 * Copyright 1994 Martin Ayotte
5 * 1996 Alex Korobka
6 * 1999 Noel Borthwick
7 * 2003 Ulrich Czekalla for CodeWeavers
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.
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.
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
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)
32 #include "config.h"
33 #include "wine/port.h"
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>
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_private.h"
53 #include "win.h"
55 #include "wine/debug.h"
56 #include "wine/unicode.h"
57 #include "wine/server.h"
59 WINE_DEFAULT_DEBUG_CHANNEL(clipboard);
61 #define CF_REGFORMATBASE 0xC000
63 typedef struct
65 HWND hWndOpen;
66 HWND hWndOwner;
67 HWND hWndViewer;
68 UINT seqno;
69 UINT flags;
70 } CLIPBOARDINFO, *LPCLIPBOARDINFO;
73 * Indicates if data has changed since open.
75 static BOOL bCBHasChanged = FALSE;
78 /**************************************************************************
79 * CLIPBOARD_SetClipboardOwner
81 * Set the global wineserver clipboard owner. The current process will
82 * be the owner and <hWnd> will get the render notifications.
84 BOOL CLIPBOARD_SetClipboardOwner(HWND hWnd)
86 BOOL bRet = FALSE;
88 TRACE(" hWnd(%p)\n", hWnd);
90 SERVER_START_REQ( set_clipboard_info )
92 req->flags = SET_CB_OWNER;
93 req->owner = WIN_GetFullHandle( hWnd );
95 if (wine_server_call_err( req ))
97 ERR("Failed to set clipboard owner to %p\n", hWnd);
99 else
101 bRet = TRUE;
104 SERVER_END_REQ;
106 return bRet;
110 /**************************************************************************
111 * CLIPBOARD_GetClipboardInfo
113 static BOOL CLIPBOARD_GetClipboardInfo(LPCLIPBOARDINFO cbInfo)
115 BOOL bRet = FALSE;
117 SERVER_START_REQ( set_clipboard_info )
119 req->flags = 0;
121 if (wine_server_call_err( req ))
123 ERR("Failed to get clipboard info\n");
125 else
127 cbInfo->hWndOpen = reply->old_clipboard;
128 cbInfo->hWndOwner = reply->old_owner;
129 cbInfo->hWndViewer = reply->old_viewer;
130 cbInfo->seqno = reply->seqno;
131 cbInfo->flags = reply->flags;
133 bRet = TRUE;
136 SERVER_END_REQ;
138 return bRet;
142 /**************************************************************************
143 * CLIPBOARD_ReleaseOwner
145 BOOL CLIPBOARD_ReleaseOwner(void)
147 BOOL bRet = FALSE;
149 SERVER_START_REQ( set_clipboard_info )
151 req->flags = SET_CB_RELOWNER | SET_CB_SEQNO;
153 if (wine_server_call_err( req ))
155 ERR("Failed to set clipboard.\n");
157 else
159 bRet = TRUE;
162 SERVER_END_REQ;
164 return bRet;
168 /**************************************************************************
169 * CLIPBOARD_OpenClipboard
171 static BOOL CLIPBOARD_OpenClipboard(HWND hWnd)
173 BOOL bRet = FALSE;
175 SERVER_START_REQ( set_clipboard_info )
177 req->flags = SET_CB_OPEN;
178 req->clipboard = WIN_GetFullHandle( hWnd );
180 if (!wine_server_call( req ))
181 bRet = TRUE;
183 SERVER_END_REQ;
185 return bRet;
189 /**************************************************************************
190 * CLIPBOARD_CloseClipboard
192 static BOOL CLIPBOARD_CloseClipboard(void)
194 BOOL bRet = FALSE;
196 TRACE(" Changed=%d\n", bCBHasChanged);
198 SERVER_START_REQ( set_clipboard_info )
200 req->flags = SET_CB_CLOSE;
202 if (bCBHasChanged)
204 req->flags |= SET_CB_SEQNO;
205 TRACE("Clipboard data changed\n");
208 if (wine_server_call_err( req ))
210 ERR("Failed to set clipboard.\n");
212 else
214 bRet = TRUE;
217 SERVER_END_REQ;
219 return bRet;
223 /**************************************************************************
224 * WIN32 Clipboard implementation
225 **************************************************************************/
227 /**************************************************************************
228 * RegisterClipboardFormatA (USER32.@)
230 UINT WINAPI RegisterClipboardFormatA(LPCSTR FormatName)
232 UINT wFormatID = 0;
234 TRACE("%s\n", debugstr_a(FormatName));
236 if (USER_Driver.pRegisterClipboardFormat)
237 wFormatID = USER_Driver.pRegisterClipboardFormat(FormatName);
239 return wFormatID;
243 /**************************************************************************
244 * RegisterClipboardFormatW (USER32.@)
246 UINT WINAPI RegisterClipboardFormatW(LPCWSTR formatName)
248 LPSTR aFormat = HEAP_strdupWtoA( GetProcessHeap(), 0, formatName );
249 UINT ret = RegisterClipboardFormatA( aFormat );
250 HeapFree( GetProcessHeap(), 0, aFormat );
251 return ret;
255 /**************************************************************************
256 * GetClipboardFormatNameA (USER32.@)
258 INT WINAPI GetClipboardFormatNameA(UINT wFormat, LPSTR retStr, INT maxlen)
260 INT len = 0;
262 TRACE("%04x,%p,%d\n", wFormat, retStr, maxlen);
264 if (USER_Driver.pGetClipboardFormatName)
265 len = USER_Driver.pGetClipboardFormatName(wFormat, retStr, maxlen);
267 return len;
271 /**************************************************************************
272 * GetClipboardFormatNameW (USER32.@)
274 INT WINAPI GetClipboardFormatNameW(UINT wFormat, LPWSTR retStr, INT maxlen)
276 INT ret;
277 LPSTR p = HeapAlloc( GetProcessHeap(), 0, maxlen );
278 if(p == NULL) return 0; /* FIXME: is this the correct failure value? */
280 ret = GetClipboardFormatNameA( wFormat, p, maxlen );
282 if (maxlen > 0 && !MultiByteToWideChar( CP_ACP, 0, p, -1, retStr, maxlen ))
283 retStr[maxlen-1] = 0;
284 HeapFree( GetProcessHeap(), 0, p );
285 return ret;
289 /**************************************************************************
290 * OpenClipboard (USER32.@)
292 * Note: Netscape uses NULL hWnd to open the clipboard.
294 BOOL WINAPI OpenClipboard( HWND hWnd )
296 BOOL bRet;
298 TRACE("(%p)...\n", hWnd);
300 bRet = CLIPBOARD_OpenClipboard(hWnd);
302 TRACE(" returning %i\n", bRet);
304 return bRet;
308 /**************************************************************************
309 * CloseClipboard (USER32.@)
311 BOOL WINAPI CloseClipboard(void)
313 BOOL bRet = FALSE;
315 TRACE("(%d)\n", bCBHasChanged);
317 if (CLIPBOARD_CloseClipboard())
319 if (bCBHasChanged)
321 HWND hWndViewer = GetClipboardViewer();
323 if (USER_Driver.pEndClipboardUpdate)
324 USER_Driver.pEndClipboardUpdate();
326 if (hWndViewer)
327 SendMessageW(hWndViewer, WM_DRAWCLIPBOARD, 0, 0);
329 bCBHasChanged = FALSE;
332 bRet = TRUE;
335 return bRet;
339 /**************************************************************************
340 * EmptyClipboard (USER32.@)
341 * Empties and acquires ownership of the clipboard
343 BOOL WINAPI EmptyClipboard(void)
345 CLIPBOARDINFO cbinfo;
347 TRACE("()\n");
349 if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
350 ~cbinfo.flags & CB_OPEN)
352 WARN("Clipboard not opened by calling task!\n");
353 SetLastError(ERROR_CLIPBOARD_NOT_OPEN);
354 return FALSE;
357 /* Destroy private objects */
358 if (cbinfo.hWndOwner)
359 SendMessageW(cbinfo.hWndOwner, WM_DESTROYCLIPBOARD, 0, 0);
361 /* Tell the driver to acquire the selection. The current owner
362 * will be signaled to delete it's own cache. */
364 /* Assign ownership of the clipboard to the current client. We do
365 * this before acquiring the selection so that when we do acquire the
366 * selection and the selection loser gets notified, it can check if
367 * it has lost the Wine clipboard ownership. If it did then it knows
368 * that a WM_DESTORYCLIPBOARD has already been sent. Otherwise it
369 * lost the selection to a X app and it should send the
370 * WM_DESTROYCLIPBOARD itself. */
371 CLIPBOARD_SetClipboardOwner(cbinfo.hWndOpen);
373 /* Acquire the selection. This will notify the previous owner
374 * to clear it's cache. */
375 if (USER_Driver.pAcquireClipboard)
376 USER_Driver.pAcquireClipboard(cbinfo.hWndOpen);
378 /* Empty the local cache */
379 if (USER_Driver.pEmptyClipboard)
380 USER_Driver.pEmptyClipboard(FALSE);
382 bCBHasChanged = TRUE;
384 return TRUE;
388 /**************************************************************************
389 * GetClipboardOwner (USER32.@)
390 * FIXME: Can't return the owner if the clipboard is owned by an external X-app
392 HWND WINAPI GetClipboardOwner(void)
394 HWND hWndOwner = 0;
396 SERVER_START_REQ( set_clipboard_info )
398 req->flags = 0;
399 if (!wine_server_call_err( req )) hWndOwner = reply->old_owner;
401 SERVER_END_REQ;
403 TRACE(" hWndOwner(%p)\n", hWndOwner);
405 return hWndOwner;
409 /**************************************************************************
410 * GetOpenClipboardWindow (USER32.@)
412 HWND WINAPI GetOpenClipboardWindow(void)
414 HWND hWndOpen = 0;
416 SERVER_START_REQ( set_clipboard_info )
418 req->flags = 0;
419 if (!wine_server_call_err( req )) hWndOpen = reply->old_clipboard;
421 SERVER_END_REQ;
423 TRACE(" hWndClipWindow(%p)\n", hWndOpen);
425 return hWndOpen;
429 /**************************************************************************
430 * SetClipboardViewer (USER32.@)
432 HWND WINAPI SetClipboardViewer( HWND hWnd )
434 HWND hwndPrev = 0;
436 SERVER_START_REQ( set_clipboard_info )
438 req->flags = SET_CB_VIEWER;
439 req->viewer = WIN_GetFullHandle(hWnd);
441 if (wine_server_call_err( req ))
443 ERR("Failed to set clipboard.\n");
445 else
447 hwndPrev = reply->old_viewer;
450 SERVER_END_REQ;
452 TRACE("(%p): returning %p\n", hWnd, hwndPrev);
454 return hwndPrev;
458 /**************************************************************************
459 * GetClipboardViewer (USER32.@)
461 HWND WINAPI GetClipboardViewer(void)
463 HWND hWndViewer = 0;
465 SERVER_START_REQ( set_clipboard_info )
467 req->flags = 0;
468 if (!wine_server_call_err( req )) hWndViewer = reply->old_viewer;
470 SERVER_END_REQ;
472 TRACE(" hWndViewer=%p\n", hWndViewer);
474 return hWndViewer;
478 /**************************************************************************
479 * ChangeClipboardChain (USER32.@)
481 BOOL WINAPI ChangeClipboardChain(HWND hWnd, HWND hWndNext)
483 BOOL bRet = TRUE;
484 HWND hWndViewer = GetClipboardViewer();
486 if (hWndViewer)
488 if (WIN_GetFullHandle(hWnd) == hWndViewer)
489 SetClipboardViewer(WIN_GetFullHandle(hWndNext));
490 else
491 bRet = !SendMessageW(hWndViewer, WM_CHANGECBCHAIN, (WPARAM)hWnd, (LPARAM)hWndNext);
493 else
494 ERR("hWndViewer is lost\n");
496 return bRet;
500 /**************************************************************************
501 * SetClipboardData (USER.141)
503 HANDLE16 WINAPI SetClipboardData16(UINT16 wFormat, HANDLE16 hData)
505 CLIPBOARDINFO cbinfo;
506 HANDLE16 hResult = 0;
508 TRACE("(%04X, %04x) !\n", wFormat, hData);
510 /* If it's not owned, data can only be set if the format doesn't exists
511 and its rendering is not delayed */
512 if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
513 (!(cbinfo.flags & CB_OWNER) && !hData))
515 WARN("Clipboard not owned by calling task. Operation failed.\n");
516 return 0;
519 if (USER_Driver.pSetClipboardData &&
520 USER_Driver.pSetClipboardData(wFormat, hData, 0, cbinfo.flags & CB_OWNER))
522 hResult = hData;
523 bCBHasChanged = TRUE;
526 return hResult;
530 /**************************************************************************
531 * SetClipboardData (USER32.@)
533 HANDLE WINAPI SetClipboardData(UINT wFormat, HANDLE hData)
535 CLIPBOARDINFO cbinfo;
536 HANDLE hResult = 0;
538 TRACE("(%04X, %p) !\n", wFormat, hData);
540 /* If it's not owned, data can only be set if the format isn't
541 available and its rendering is not delayed */
542 if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
543 (!(cbinfo.flags & CB_OWNER) && !hData))
545 WARN("Clipboard not owned by calling task. Operation failed.\n");
546 return 0;
549 if (USER_Driver.pSetClipboardData &&
550 USER_Driver.pSetClipboardData(wFormat, 0, hData, cbinfo.flags & CB_OWNER))
552 hResult = hData;
553 bCBHasChanged = TRUE;
556 return hResult;
560 /**************************************************************************
561 * CountClipboardFormats (USER32.@)
563 INT WINAPI CountClipboardFormats(void)
565 INT count = 0;
567 if (USER_Driver.pCountClipboardFormats)
568 count = USER_Driver.pCountClipboardFormats();
570 TRACE("returning %d\n", count);
571 return count;
575 /**************************************************************************
576 * EnumClipboardFormats (USER32.@)
578 UINT WINAPI EnumClipboardFormats(UINT wFormat)
580 UINT wFmt = 0;
581 CLIPBOARDINFO cbinfo;
583 TRACE("(%04X)\n", wFormat);
585 if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
586 (~cbinfo.flags & CB_OPEN))
588 WARN("Clipboard not opened by calling task.\n");
589 SetLastError(ERROR_CLIPBOARD_NOT_OPEN);
590 return 0;
593 if (USER_Driver.pEnumClipboardFormats)
594 wFmt = USER_Driver.pEnumClipboardFormats(wFormat);
596 return wFmt;
600 /**************************************************************************
601 * IsClipboardFormatAvailable (USER32.@)
603 BOOL WINAPI IsClipboardFormatAvailable(UINT wFormat)
605 BOOL bret = FALSE;
607 if (USER_Driver.pIsClipboardFormatAvailable)
608 bret = USER_Driver.pIsClipboardFormatAvailable(wFormat);
610 TRACE("%04x, returning %d\n", wFormat, bret);
611 return bret;
615 /**************************************************************************
616 * GetClipboardData (USER.142)
618 HANDLE16 WINAPI GetClipboardData16(UINT16 wFormat)
620 HANDLE16 hData = 0;
621 CLIPBOARDINFO cbinfo;
623 if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
624 (~cbinfo.flags & CB_OPEN))
626 WARN("Clipboard not opened by calling task.\n");
627 SetLastError(ERROR_CLIPBOARD_NOT_OPEN);
628 return 0;
631 if (USER_Driver.pGetClipboardData)
632 USER_Driver.pGetClipboardData(wFormat, &hData, NULL);
634 return hData;
638 /**************************************************************************
639 * GetClipboardData (USER32.@)
641 HANDLE WINAPI GetClipboardData(UINT wFormat)
643 HANDLE hData = 0;
644 CLIPBOARDINFO cbinfo;
646 TRACE("%04x\n", wFormat);
648 if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
649 (~cbinfo.flags & CB_OPEN))
651 WARN("Clipboard not opened by calling task.\n");
652 SetLastError(ERROR_CLIPBOARD_NOT_OPEN);
653 return 0;
656 if (USER_Driver.pGetClipboardData)
657 USER_Driver.pGetClipboardData(wFormat, NULL, &hData);
659 TRACE("returning %p\n", hData);
660 return hData;
664 /**************************************************************************
665 * GetPriorityClipboardFormat (USER32.@)
667 INT WINAPI GetPriorityClipboardFormat(UINT *list, INT nCount)
669 int i;
671 TRACE("()\n");
673 if(CountClipboardFormats() == 0)
674 return 0;
676 for (i = 0; i < nCount; i++)
677 if (IsClipboardFormatAvailable(list[i]))
678 return list[i];
680 return -1;
684 /**************************************************************************
685 * GetClipboardSequenceNumber (USER32.@)
686 * Supported on Win2k/Win98
687 * MSDN: Windows clipboard code keeps a serial number for the clipboard
688 * for each window station. The number is incremented whenever the
689 * contents change or are emptied.
690 * If you do not have WINSTA_ACCESSCLIPBOARD then the function returns 0
692 DWORD WINAPI GetClipboardSequenceNumber(VOID)
694 DWORD seqno = 0;
696 SERVER_START_REQ( set_clipboard_info )
698 req->flags = 0;
699 if (!wine_server_call_err( req )) seqno = reply->seqno;
701 SERVER_END_REQ;
703 TRACE("returning %lx\n", seqno);
704 return seqno;