blob: aa27a9842e881189f9d539e74ad4fefb7c06261f [file] [log] [blame]
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001/*
Noel Borthwick29700671999-09-03 15:17:57 +00002 * WIN32 clipboard implementation
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00003 *
4 * Copyright 1994 Martin Ayotte
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00005 * 1996 Alex Korobka
Noel Borthwick29700671999-09-03 15:17:57 +00006 * 1999 Noel Borthwick
Ulrich Czekallab2df5f92003-06-23 23:02:02 +00007 * 2003 Ulrich Czekalla for CodeWeavers
Noel Borthwick29700671999-09-03 15:17:57 +00008 *
Alexandre Julliard0799c1a2002-03-09 23:29:33 +00009 * 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 *
Noel Borthwick29700671999-09-03 15:17:57 +000023 * 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)
Alexandre Julliard1e9ac791996-06-06 18:38:27 +000030 */
Alexandre Julliardfb9a9191994-03-01 19:48:04 +000031
Patrik Stridvalld016f812002-08-17 00:43:16 +000032#include "config.h"
Patrik Stridvall51e6c0c2002-08-31 19:04:14 +000033#include "wine/port.h"
Patrik Stridvalld016f812002-08-17 00:43:16 +000034
Alexandre Julliarde37c6e12003-09-05 23:08:26 +000035#include <stdarg.h>
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000036#include <stdlib.h>
Alexandre Julliardfb9a9191994-03-01 19:48:04 +000037#include <sys/types.h>
Alexandre Julliardfb9a9191994-03-01 19:48:04 +000038#include <fcntl.h>
Patrik Stridvalld016f812002-08-17 00:43:16 +000039#ifdef HAVE_UNISTD_H
40# include <unistd.h>
41#endif
Alexandre Julliard1e9ac791996-06-06 18:38:27 +000042#include <string.h>
François Gouget44a18222000-12-19 04:53:20 +000043
Jeremy Whited3e22d92000-02-10 19:03:02 +000044#include "windef.h"
François Gouget44a18222000-12-19 04:53:20 +000045#include "winbase.h"
Jeremy Whited3e22d92000-02-10 19:03:02 +000046#include "wingdi.h"
Marcus Meissner61afa331999-02-22 10:16:00 +000047#include "winuser.h"
Ulrich Czekallab2df5f92003-06-23 23:02:02 +000048#include "winerror.h"
Marcus Meissner219cfd81999-02-24 13:05:13 +000049#include "wine/winuser16.h"
Noel Borthwick29700671999-09-03 15:17:57 +000050#include "wine/winbase16.h"
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +000051#include "heap.h"
Alexandre Julliard42d20f92000-08-10 01:16:19 +000052#include "user.h"
Alexandre Julliard37a46392001-09-12 17:19:13 +000053#include "win.h"
Patrik Stridvallcf07e102002-10-23 20:20:59 +000054
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000055#include "wine/debug.h"
Patrik Stridvallcf07e102002-10-23 20:20:59 +000056#include "wine/unicode.h"
Ulrich Czekallab2df5f92003-06-23 23:02:02 +000057#include "wine/server.h"
Alexandre Julliardfb9a9191994-03-01 19:48:04 +000058
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000059WINE_DEFAULT_DEBUG_CHANNEL(clipboard);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000060
Alexandre Julliard1e9ac791996-06-06 18:38:27 +000061#define CF_REGFORMATBASE 0xC000
62
Alexandre Julliard5329fc82003-12-05 04:45:50 +000063typedef struct
64{
65 HWND hWndOpen;
66 HWND hWndOwner;
67 HWND hWndViewer;
68 UINT seqno;
69 UINT flags;
70} CLIPBOARDINFO, *LPCLIPBOARDINFO;
Alexandre Julliarda8a422f2002-11-22 20:43:01 +000071
Ulrich Czekallab2df5f92003-06-23 23:02:02 +000072/*
73 * Indicates if data has changed since open.
Alexandre Julliard1e9ac791996-06-06 18:38:27 +000074 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +000075static BOOL bCBHasChanged = FALSE;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +000076
Noel Borthwick29700671999-09-03 15:17:57 +000077
78/**************************************************************************
Ulrich Czekallab2df5f92003-06-23 23:02:02 +000079 * CLIPBOARD_SetClipboardOwner
Noel Borthwick29700671999-09-03 15:17:57 +000080 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +000081BOOL CLIPBOARD_SetClipboardOwner(HWND hWnd)
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +000082{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +000083 BOOL bRet = FALSE;
84
85 TRACE(" hWnd(%p)\n", hWnd);
86
87 SERVER_START_REQ( set_clipboard_info )
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +000088 {
Ulrich Czekallab2df5f92003-06-23 23:02:02 +000089 req->flags = SET_CB_OWNER;
90 req->owner = WIN_GetFullHandle( hWnd );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +000091
Ulrich Czekallab2df5f92003-06-23 23:02:02 +000092 if (wine_server_call_err( req ))
Noel Borthwick29700671999-09-03 15:17:57 +000093 {
Ulrich Czekallab2df5f92003-06-23 23:02:02 +000094 ERR("Failed to set clipboard.\n");
Gerard Patel9289a5d2000-12-22 23:26:18 +000095 }
96 else
97 {
Ulrich Czekallab2df5f92003-06-23 23:02:02 +000098 bRet = TRUE;
Gerard Patel9289a5d2000-12-22 23:26:18 +000099 }
Noel Borthwick29700671999-09-03 15:17:57 +0000100 }
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000101 SERVER_END_REQ;
Noel Borthwick29700671999-09-03 15:17:57 +0000102
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000103 return bRet;
Noel Borthwick29700671999-09-03 15:17:57 +0000104}
105
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000106
Noel Borthwick29700671999-09-03 15:17:57 +0000107/**************************************************************************
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000108 * CLIPBOARD_GetClipboardInfo
Gerard Patel9289a5d2000-12-22 23:26:18 +0000109 */
Alexandre Julliard5329fc82003-12-05 04:45:50 +0000110static BOOL CLIPBOARD_GetClipboardInfo(LPCLIPBOARDINFO cbInfo)
Gerard Patel9289a5d2000-12-22 23:26:18 +0000111{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000112 BOOL bRet = FALSE;
Gerard Patel9289a5d2000-12-22 23:26:18 +0000113
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000114 SERVER_START_REQ( set_clipboard_info )
Gerard Patel9289a5d2000-12-22 23:26:18 +0000115 {
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000116 req->flags = 0;
Gerard Patel9289a5d2000-12-22 23:26:18 +0000117
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000118 if (wine_server_call_err( req ))
Gerard Patel9289a5d2000-12-22 23:26:18 +0000119 {
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000120 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;
Gerard Patel9289a5d2000-12-22 23:26:18 +0000129
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000130 bRet = TRUE;
131 }
132 }
133 SERVER_END_REQ;
134
135 return bRet;
136}
137
138
139/**************************************************************************
140 * CLIPBOARD_ReleaseOwner
141 */
142BOOL 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 */
168static 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 */
195static 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");
Gerard Patel9289a5d2000-12-22 23:26:18 +0000209 }
210
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000211 if (wine_server_call_err( req ))
212 {
213 ERR("Failed to set clipboard.\n");
214 }
215 else
216 {
217 bRet = TRUE;
218 }
Gerard Patel9289a5d2000-12-22 23:26:18 +0000219 }
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000220 SERVER_END_REQ;
Gerard Patel9289a5d2000-12-22 23:26:18 +0000221
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000222 return bRet;
Gerard Patel9289a5d2000-12-22 23:26:18 +0000223}
224
225
226/**************************************************************************
Vincent Béron9a624912002-05-31 23:06:46 +0000227 * WIN32 Clipboard implementation
Noel Borthwick29700671999-09-03 15:17:57 +0000228 **************************************************************************/
229
230/**************************************************************************
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000231 * RegisterClipboardFormatA (USER32.@)
232 */
233UINT 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 */
249UINT16 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 */
265UINT 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 */
277INT16 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 */
288INT 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 */
304INT 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/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000320 * OpenClipboard (USER32.@)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000321 *
322 * Note: Netscape uses NULL hWnd to open the clipboard.
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000323 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000324BOOL WINAPI OpenClipboard( HWND hWnd )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000325{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000326 BOOL bRet;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000327
Alexandre Julliardaff7dda2002-11-22 21:22:14 +0000328 TRACE("(%p)...\n", hWnd);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000329
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000330 bRet = CLIPBOARD_OpenClipboard(hWnd);
Noel Borthwick29700671999-09-03 15:17:57 +0000331
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000332 TRACE(" returning %i\n", bRet);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000333
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000334 return bRet;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000335}
336
337
338/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000339 * CloseClipboard (USER.138)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000340 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000341BOOL16 WINAPI CloseClipboard16(void)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000342{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000343 return CloseClipboard();
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000344}
345
346
347/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000348 * CloseClipboard (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000349 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000350BOOL WINAPI CloseClipboard(void)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000351{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000352 BOOL bRet = FALSE;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000353
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000354 TRACE("(%d)\n", bCBHasChanged);
355
356 if (CLIPBOARD_CloseClipboard())
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000357 {
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000358 if (bCBHasChanged)
359 {
360 HWND hWndViewer = GetClipboardViewer();
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000361
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000362 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;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000372 }
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000373
374 return bRet;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000375}
376
377
378/**************************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +0000379 * EmptyClipboard (USER.139)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000380 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000381BOOL16 WINAPI EmptyClipboard16(void)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000382{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000383 return EmptyClipboard();
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000384}
385
386
387/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000388 * EmptyClipboard (USER32.@)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000389 * Empties and acquires ownership of the clipboard
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000390 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000391BOOL WINAPI EmptyClipboard(void)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000392{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000393 CLIPBOARDINFO cbinfo;
394
Noel Borthwick29700671999-09-03 15:17:57 +0000395 TRACE("()\n");
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000396
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000397 if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
398 ~cbinfo.flags & CB_OPEN)
399 {
Francois Gougete76218d2001-05-09 17:31:31 +0000400 WARN("Clipboard not opened by calling task!\n");
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000401 SetLastError(ERROR_CLIPBOARD_NOT_OPEN);
Noel Borthwick29700671999-09-03 15:17:57 +0000402 return FALSE;
403 }
Vincent Béron9a624912002-05-31 23:06:46 +0000404
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000405 /* Destroy private objects */
406 if (cbinfo.hWndOwner)
407 SendMessageW(cbinfo.hWndOwner, WM_DESTROYCLIPBOARD, 0, 0);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000408
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000409 /* 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);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000421
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000422 /* 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 }
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000427
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000428 /* Empty the local cache */
429 if (USER_Driver.pEmptyClipboard)
Ulrich Czekallab41466b2004-05-06 23:40:30 +0000430 USER_Driver.pEmptyClipboard(FALSE);
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000431
432 bCBHasChanged = TRUE;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000433
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000434 return TRUE;
435}
436
437
438/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000439 * GetClipboardOwner (USER32.@)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000440 * FIXME: Can't return the owner if the clipboard is owned by an external X-app
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000441 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000442HWND WINAPI GetClipboardOwner(void)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000443{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000444 HWND hWndOwner = 0;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000445
Alexandre Julliard5329fc82003-12-05 04:45:50 +0000446 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;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000452
453 TRACE(" hWndOwner(%p)\n", hWndOwner);
454
455 return hWndOwner;
456}
457
458
459/**************************************************************************
460 * GetOpenClipboardWindow (USER32.@)
461 */
462HWND WINAPI GetOpenClipboardWindow(void)
463{
464 HWND hWndOpen = 0;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000465
Alexandre Julliard5329fc82003-12-05 04:45:50 +0000466 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;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000472
473 TRACE(" hWndClipWindow(%p)\n", hWndOpen);
474
475 return hWndOpen;
476}
477
478
479/**************************************************************************
480 * SetClipboardViewer (USER32.@)
481 */
482HWND 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 */
511HWND WINAPI GetClipboardViewer(void)
512{
513 HWND hWndViewer = 0;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000514
Alexandre Julliard5329fc82003-12-05 04:45:50 +0000515 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;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000521
522 TRACE(" hWndViewer=%p\n", hWndViewer);
523
524 return hWndViewer;
525}
526
527
528/**************************************************************************
529 * ChangeClipboardChain (USER32.@)
530 */
531BOOL 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;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000547}
548
549
550/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000551 * SetClipboardData (USER.141)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000552 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000553HANDLE16 WINAPI SetClipboardData16(UINT16 wFormat, HANDLE16 hData)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000554{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000555 CLIPBOARDINFO cbinfo;
556 HANDLE16 hResult = 0;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000557
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000558 TRACE("(%04X, %04x) !\n", wFormat, hData);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000559
Ulrich Czekallab41466b2004-05-06 23:40:30 +0000560 /* If it's not owned, data can only be set if the format doesn't exists
561 and its rendering is not delayed */
Ulrich Czekalla4e10f0e2004-05-10 19:59:36 +0000562 if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
563 (!(cbinfo.flags & CB_OWNER) && !hData))
Ulrich Czekallab41466b2004-05-06 23:40:30 +0000564 {
565 WARN("Clipboard not owned by calling task. Operation failed.\n");
566 return 0;
567 }
568
569 if (USER_Driver.pSetClipboardData &&
570 USER_Driver.pSetClipboardData(wFormat, hData, 0, cbinfo.flags & CB_OWNER))
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000571 {
572 hResult = hData;
573 bCBHasChanged = TRUE;
Noel Borthwick29700671999-09-03 15:17:57 +0000574 }
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000575
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000576 return hResult;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000577}
578
Alexandre Julliard21979011997-03-05 08:22:35 +0000579
580/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000581 * SetClipboardData (USER32.@)
Alexandre Julliard21979011997-03-05 08:22:35 +0000582 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000583HANDLE WINAPI SetClipboardData(UINT wFormat, HANDLE hData)
Alexandre Julliard21979011997-03-05 08:22:35 +0000584{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000585 CLIPBOARDINFO cbinfo;
586 HANDLE hResult = 0;
Pascal Cuoq724f1901998-10-26 10:58:16 +0000587
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000588 TRACE("(%04X, %p) !\n", wFormat, hData);
Pascal Cuoq724f1901998-10-26 10:58:16 +0000589
Ulrich Czekallab41466b2004-05-06 23:40:30 +0000590 /* If it's not owned, data can only be set if the format isn't
591 available and its rendering is not delayed */
Ulrich Czekalla4e10f0e2004-05-10 19:59:36 +0000592 if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
593 (!(cbinfo.flags & CB_OWNER) && !hData))
Ulrich Czekallab41466b2004-05-06 23:40:30 +0000594 {
595 WARN("Clipboard not owned by calling task. Operation failed.\n");
596 return 0;
597 }
598
599 if (USER_Driver.pSetClipboardData &&
600 USER_Driver.pSetClipboardData(wFormat, 0, hData, cbinfo.flags & CB_OWNER))
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000601 {
602 hResult = hData;
603 bCBHasChanged = TRUE;
Noel Borthwick29700671999-09-03 15:17:57 +0000604 }
Pascal Cuoq724f1901998-10-26 10:58:16 +0000605
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000606 return hResult;
Alexandre Julliard21979011997-03-05 08:22:35 +0000607}
608
Noel Borthwick29700671999-09-03 15:17:57 +0000609
Alexandre Julliard21979011997-03-05 08:22:35 +0000610/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000611 * CountClipboardFormats (USER.143)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000612 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000613INT16 WINAPI CountClipboardFormats16(void)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000614{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000615 return CountClipboardFormats();
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000616}
617
618
619/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000620 * CountClipboardFormats (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000621 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000622INT WINAPI CountClipboardFormats(void)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000623{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000624 INT count = 0;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000625
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000626 if (USER_Driver.pCountClipboardFormats)
627 count = USER_Driver.pCountClipboardFormats();
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000628
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000629 TRACE("returning %d\n", count);
630 return count;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000631}
632
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000633
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000634/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000635 * EnumClipboardFormats (USER.144)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000636 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000637UINT16 WINAPI EnumClipboardFormats16(UINT16 wFormat)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000638{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000639 return EnumClipboardFormats(wFormat);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000640}
641
642
643/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000644 * EnumClipboardFormats (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000645 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000646UINT WINAPI EnumClipboardFormats(UINT wFormat)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000647{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000648 UINT wFmt = 0;
649 CLIPBOARDINFO cbinfo;
650
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000651 TRACE("(%04X)\n", wFormat);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000652
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000653 if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
654 (~cbinfo.flags & CB_OPEN))
Noel Borthwick29700671999-09-03 15:17:57 +0000655 {
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000656 WARN("Clipboard not opened by calling task.\n");
657 SetLastError(ERROR_CLIPBOARD_NOT_OPEN);
Noel Borthwick29700671999-09-03 15:17:57 +0000658 return 0;
659 }
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000660
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000661 if (USER_Driver.pEnumClipboardFormats)
662 wFmt = USER_Driver.pEnumClipboardFormats(wFormat);
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000663
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000664 return wFmt;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000665}
666
667
668/**************************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +0000669 * IsClipboardFormatAvailable (USER.193)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000670 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000671BOOL16 WINAPI IsClipboardFormatAvailable16(UINT16 wFormat)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000672{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000673 return IsClipboardFormatAvailable(wFormat);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000674}
675
676
677/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000678 * IsClipboardFormatAvailable (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000679 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000680BOOL WINAPI IsClipboardFormatAvailable(UINT wFormat)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000681{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000682 BOOL bret = FALSE;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000683
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000684 if (USER_Driver.pIsClipboardFormatAvailable)
685 bret = USER_Driver.pIsClipboardFormatAvailable(wFormat);
686
687 TRACE("%04x, returning %d\n", wFormat, bret);
688 return bret;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000689}
690
691
692/**************************************************************************
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000693 * GetClipboardData (USER.142)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000694 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000695HANDLE16 WINAPI GetClipboardData16(UINT16 wFormat)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000696{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000697 HANDLE16 hData = 0;
698 CLIPBOARDINFO cbinfo;
699
700 if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
701 (~cbinfo.flags & CB_OPEN))
702 {
703 WARN("Clipboard not opened by calling task.\n");
704 SetLastError(ERROR_CLIPBOARD_NOT_OPEN);
705 return 0;
706 }
707
708 if (USER_Driver.pGetClipboardData)
709 USER_Driver.pGetClipboardData(wFormat, &hData, NULL);
710
711 return hData;
712}
713
714
715/**************************************************************************
716 * GetClipboardData (USER32.@)
717 */
718HANDLE WINAPI GetClipboardData(UINT wFormat)
719{
720 HANDLE hData = 0;
721 CLIPBOARDINFO cbinfo;
722
723 TRACE("%04x\n", wFormat);
724
725 if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
726 (~cbinfo.flags & CB_OPEN))
727 {
728 WARN("Clipboard not opened by calling task.\n");
729 SetLastError(ERROR_CLIPBOARD_NOT_OPEN);
730 return 0;
731 }
732
733 if (USER_Driver.pGetClipboardData)
734 USER_Driver.pGetClipboardData(wFormat, NULL, &hData);
735
736 TRACE("returning %p\n", hData);
737 return hData;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000738}
739
740
741/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000742 * GetPriorityClipboardFormat (USER32.@)
Alexandre Julliard21979011997-03-05 08:22:35 +0000743 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000744INT WINAPI GetPriorityClipboardFormat(UINT *list, INT nCount)
Alexandre Julliard21979011997-03-05 08:22:35 +0000745{
Alexandre Julliardd23a82b2001-09-19 20:37:04 +0000746 int i;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000747
Noel Borthwick29700671999-09-03 15:17:57 +0000748 TRACE("()\n");
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000749
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000750 if(CountClipboardFormats() == 0)
751 return 0;
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000752
Alexandre Julliardd23a82b2001-09-19 20:37:04 +0000753 for (i = 0; i < nCount; i++)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000754 if (IsClipboardFormatAvailable(list[i]))
755 return list[i];
756
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000757 return -1;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000758}
759
David Elliott44f84b52000-10-29 01:24:54 +0000760
761/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000762 * GetClipboardSequenceNumber (USER32.@)
David Elliott44f84b52000-10-29 01:24:54 +0000763 * Supported on Win2k/Win98
764 * MSDN: Windows clipboard code keeps a serial number for the clipboard
765 * for each window station. The number is incremented whenever the
766 * contents change or are emptied.
767 * If you do not have WINSTA_ACCESSCLIPBOARD then the function returns 0
768 */
769DWORD WINAPI GetClipboardSequenceNumber(VOID)
770{
Alexandre Julliard5329fc82003-12-05 04:45:50 +0000771 DWORD seqno = 0;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000772
Alexandre Julliard5329fc82003-12-05 04:45:50 +0000773 SERVER_START_REQ( set_clipboard_info )
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000774 {
Alexandre Julliard5329fc82003-12-05 04:45:50 +0000775 req->flags = 0;
776 if (!wine_server_call_err( req )) seqno = reply->seqno;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000777 }
Alexandre Julliard5329fc82003-12-05 04:45:50 +0000778 SERVER_END_REQ;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000779
Alexandre Julliard5329fc82003-12-05 04:45:50 +0000780 TRACE("returning %lx\n", seqno);
781 return seqno;
David Elliott44f84b52000-10-29 01:24:54 +0000782}