blob: d1bbce444c07f389746d2f195738677cb7c91e7a [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"
Alexandre Julliard234bc241994-12-10 13:02:28 +000054#include "clipboard.h"
Patrik Stridvallcf07e102002-10-23 20:20:59 +000055
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000056#include "wine/debug.h"
Patrik Stridvallcf07e102002-10-23 20:20:59 +000057#include "wine/unicode.h"
Ulrich Czekallab2df5f92003-06-23 23:02:02 +000058#include "wine/server.h"
Alexandre Julliardfb9a9191994-03-01 19:48:04 +000059
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000060WINE_DEFAULT_DEBUG_CHANNEL(clipboard);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000061
Alexandre Julliard1e9ac791996-06-06 18:38:27 +000062#define CF_REGFORMATBASE 0xC000
63
Alexandre Julliarda8a422f2002-11-22 20:43:01 +000064
Ulrich Czekallab2df5f92003-06-23 23:02:02 +000065/*
66 * Indicates if data has changed since open.
Alexandre Julliard1e9ac791996-06-06 18:38:27 +000067 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +000068static BOOL bCBHasChanged = FALSE;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +000069
Noel Borthwick29700671999-09-03 15:17:57 +000070
71/**************************************************************************
Ulrich Czekallab2df5f92003-06-23 23:02:02 +000072 * CLIPBOARD_SetClipboardOwner
Noel Borthwick29700671999-09-03 15:17:57 +000073 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +000074BOOL CLIPBOARD_SetClipboardOwner(HWND hWnd)
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +000075{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +000076 BOOL bRet = FALSE;
77
78 TRACE(" hWnd(%p)\n", hWnd);
79
80 SERVER_START_REQ( set_clipboard_info )
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +000081 {
Ulrich Czekallab2df5f92003-06-23 23:02:02 +000082 req->flags = SET_CB_OWNER;
83 req->owner = WIN_GetFullHandle( hWnd );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +000084
Ulrich Czekallab2df5f92003-06-23 23:02:02 +000085 if (wine_server_call_err( req ))
Noel Borthwick29700671999-09-03 15:17:57 +000086 {
Ulrich Czekallab2df5f92003-06-23 23:02:02 +000087 ERR("Failed to set clipboard.\n");
Gerard Patel9289a5d2000-12-22 23:26:18 +000088 }
89 else
90 {
Ulrich Czekallab2df5f92003-06-23 23:02:02 +000091 bRet = TRUE;
Gerard Patel9289a5d2000-12-22 23:26:18 +000092 }
Noel Borthwick29700671999-09-03 15:17:57 +000093 }
Ulrich Czekallab2df5f92003-06-23 23:02:02 +000094 SERVER_END_REQ;
Noel Borthwick29700671999-09-03 15:17:57 +000095
Ulrich Czekallab2df5f92003-06-23 23:02:02 +000096 return bRet;
Noel Borthwick29700671999-09-03 15:17:57 +000097}
98
Ulrich Czekallab2df5f92003-06-23 23:02:02 +000099
Noel Borthwick29700671999-09-03 15:17:57 +0000100/**************************************************************************
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000101 * CLIPBOARD_GetClipboardInfo
Gerard Patel9289a5d2000-12-22 23:26:18 +0000102 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000103BOOL CLIPBOARD_GetClipboardInfo(LPCLIPBOARDINFO cbInfo)
Gerard Patel9289a5d2000-12-22 23:26:18 +0000104{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000105 BOOL bRet = FALSE;
Gerard Patel9289a5d2000-12-22 23:26:18 +0000106
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000107 SERVER_START_REQ( set_clipboard_info )
Gerard Patel9289a5d2000-12-22 23:26:18 +0000108 {
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000109 req->flags = 0;
Gerard Patel9289a5d2000-12-22 23:26:18 +0000110
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000111 if (wine_server_call_err( req ))
Gerard Patel9289a5d2000-12-22 23:26:18 +0000112 {
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000113 ERR("Failed to get clipboard owner.\n");
114 }
115 else
116 {
117 cbInfo->hWndOpen = reply->old_clipboard;
118 cbInfo->hWndOwner = reply->old_owner;
119 cbInfo->hWndViewer = reply->old_viewer;
120 cbInfo->seqno = reply->seqno;
121 cbInfo->flags = reply->flags;
Gerard Patel9289a5d2000-12-22 23:26:18 +0000122
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000123 bRet = TRUE;
124 }
125 }
126 SERVER_END_REQ;
127
128 return bRet;
129}
130
131
132/**************************************************************************
133 * CLIPBOARD_ReleaseOwner
134 */
135BOOL CLIPBOARD_ReleaseOwner(void)
136{
137 BOOL bRet = FALSE;
138
139 SERVER_START_REQ( set_clipboard_info )
140 {
141 req->flags = SET_CB_RELOWNER | SET_CB_SEQNO;
142
143 if (wine_server_call_err( req ))
144 {
145 ERR("Failed to set clipboard.\n");
146 }
147 else
148 {
149 bRet = TRUE;
150 }
151 }
152 SERVER_END_REQ;
153
154 return bRet;
155}
156
157
158/**************************************************************************
159 * CLIPBOARD_OpenClipboard
160 */
161static BOOL CLIPBOARD_OpenClipboard(HWND hWnd)
162{
163 BOOL bRet = FALSE;
164
165 SERVER_START_REQ( set_clipboard_info )
166 {
167 req->flags = SET_CB_OPEN;
168 req->clipboard = WIN_GetFullHandle( hWnd );
169
170 if (wine_server_call_err( req ))
171 {
172 ERR("Failed to set clipboard.\n");
173 }
174 else
175 {
176 bRet = TRUE;
177 }
178 }
179 SERVER_END_REQ;
180
181 return bRet;
182}
183
184
185/**************************************************************************
186 * CLIPBOARD_CloseClipboard
187 */
188static BOOL CLIPBOARD_CloseClipboard(void)
189{
190 BOOL bRet = FALSE;
191
192 TRACE(" Changed=%d\n", bCBHasChanged);
193
194 SERVER_START_REQ( set_clipboard_info )
195 {
196 req->flags = SET_CB_CLOSE;
197
198 if (bCBHasChanged)
199 {
200 req->flags |= SET_CB_SEQNO;
201 TRACE("Clipboard data changed\n");
Gerard Patel9289a5d2000-12-22 23:26:18 +0000202 }
203
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000204 if (wine_server_call_err( req ))
205 {
206 ERR("Failed to set clipboard.\n");
207 }
208 else
209 {
210 bRet = TRUE;
211 }
Gerard Patel9289a5d2000-12-22 23:26:18 +0000212 }
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000213 SERVER_END_REQ;
Gerard Patel9289a5d2000-12-22 23:26:18 +0000214
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000215 return bRet;
Gerard Patel9289a5d2000-12-22 23:26:18 +0000216}
217
218
219/**************************************************************************
Vincent Béron9a624912002-05-31 23:06:46 +0000220 * WIN32 Clipboard implementation
Noel Borthwick29700671999-09-03 15:17:57 +0000221 **************************************************************************/
222
223/**************************************************************************
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000224 * RegisterClipboardFormatA (USER32.@)
225 */
226UINT WINAPI RegisterClipboardFormatA(LPCSTR FormatName)
227{
228 UINT wFormatID = 0;
229
230 TRACE("%s\n", debugstr_a(FormatName));
231
232 if (USER_Driver.pRegisterClipboardFormat)
233 wFormatID = USER_Driver.pRegisterClipboardFormat(FormatName);
234
235 return wFormatID;
236}
237
238
239/**************************************************************************
240 * RegisterClipboardFormat (USER.145)
241 */
242UINT16 WINAPI RegisterClipboardFormat16(LPCSTR FormatName)
243{
244 UINT wFormatID = 0;
245
246 TRACE("%s\n", debugstr_a(FormatName));
247
248 if (USER_Driver.pRegisterClipboardFormat)
249 wFormatID = USER_Driver.pRegisterClipboardFormat(FormatName);
250
251 return wFormatID;
252}
253
254
255/**************************************************************************
256 * RegisterClipboardFormatW (USER32.@)
257 */
258UINT WINAPI RegisterClipboardFormatW(LPCWSTR formatName)
259{
260 LPSTR aFormat = HEAP_strdupWtoA( GetProcessHeap(), 0, formatName );
261 UINT ret = RegisterClipboardFormatA( aFormat );
262 HeapFree( GetProcessHeap(), 0, aFormat );
263 return ret;
264}
265
266
267/**************************************************************************
268 * GetClipboardFormatName (USER.146)
269 */
270INT16 WINAPI GetClipboardFormatName16(UINT16 wFormat, LPSTR retStr, INT16 maxlen)
271{
272 TRACE("%04x,%p,%d\n", wFormat, retStr, maxlen);
273
274 return GetClipboardFormatNameA(wFormat, retStr, maxlen);
275}
276
277
278/**************************************************************************
279 * GetClipboardFormatNameA (USER32.@)
280 */
281INT WINAPI GetClipboardFormatNameA(UINT wFormat, LPSTR retStr, INT maxlen)
282{
283 INT len = 0;
284
285 TRACE("%04x,%p,%d\n", wFormat, retStr, maxlen);
286
287 if (USER_Driver.pGetClipboardFormatName)
288 len = USER_Driver.pGetClipboardFormatName(wFormat, retStr, maxlen);
289
290 return len;
291}
292
293
294/**************************************************************************
295 * GetClipboardFormatNameW (USER32.@)
296 */
297INT WINAPI GetClipboardFormatNameW(UINT wFormat, LPWSTR retStr, INT maxlen)
298{
299 INT ret;
300 LPSTR p = HeapAlloc( GetProcessHeap(), 0, maxlen );
301 if(p == NULL) return 0; /* FIXME: is this the correct failure value? */
302
303 ret = GetClipboardFormatNameA( wFormat, p, maxlen );
304
305 if (maxlen > 0 && !MultiByteToWideChar( CP_ACP, 0, p, -1, retStr, maxlen ))
306 retStr[maxlen-1] = 0;
307 HeapFree( GetProcessHeap(), 0, p );
308 return ret;
309}
310
311
312/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000313 * OpenClipboard (USER32.@)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000314 *
315 * Note: Netscape uses NULL hWnd to open the clipboard.
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000316 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000317BOOL WINAPI OpenClipboard( HWND hWnd )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000318{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000319 BOOL bRet;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000320
Alexandre Julliardaff7dda2002-11-22 21:22:14 +0000321 TRACE("(%p)...\n", hWnd);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000322
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000323 bRet = CLIPBOARD_OpenClipboard(hWnd);
Noel Borthwick29700671999-09-03 15:17:57 +0000324
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000325 TRACE(" returning %i\n", bRet);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000326
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000327 return bRet;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000328}
329
330
331/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000332 * CloseClipboard (USER.138)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000333 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000334BOOL16 WINAPI CloseClipboard16(void)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000335{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000336 return CloseClipboard();
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000337}
338
339
340/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000341 * CloseClipboard (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000342 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000343BOOL WINAPI CloseClipboard(void)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000344{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000345 BOOL bRet = FALSE;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000346
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000347 TRACE("(%d)\n", bCBHasChanged);
348
349 if (CLIPBOARD_CloseClipboard())
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000350 {
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000351 if (bCBHasChanged)
352 {
353 HWND hWndViewer = GetClipboardViewer();
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000354
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000355 if (USER_Driver.pEndClipboardUpdate)
356 USER_Driver.pEndClipboardUpdate();
357
358 if (hWndViewer)
359 SendMessageW(hWndViewer, WM_DRAWCLIPBOARD, 0, 0);
360
361 bCBHasChanged = FALSE;
362 }
363
364 bRet = TRUE;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000365 }
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000366
367 return bRet;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000368}
369
370
371/**************************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +0000372 * EmptyClipboard (USER.139)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000373 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000374BOOL16 WINAPI EmptyClipboard16(void)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000375{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000376 return EmptyClipboard();
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000377}
378
379
380/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000381 * EmptyClipboard (USER32.@)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000382 * Empties and acquires ownership of the clipboard
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000383 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000384BOOL WINAPI EmptyClipboard(void)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000385{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000386 CLIPBOARDINFO cbinfo;
387
Noel Borthwick29700671999-09-03 15:17:57 +0000388 TRACE("()\n");
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000389
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000390 if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
391 ~cbinfo.flags & CB_OPEN)
392 {
Francois Gougete76218d2001-05-09 17:31:31 +0000393 WARN("Clipboard not opened by calling task!\n");
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000394 SetLastError(ERROR_CLIPBOARD_NOT_OPEN);
Noel Borthwick29700671999-09-03 15:17:57 +0000395 return FALSE;
396 }
Vincent Béron9a624912002-05-31 23:06:46 +0000397
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000398 /* Destroy private objects */
399 if (cbinfo.hWndOwner)
400 SendMessageW(cbinfo.hWndOwner, WM_DESTROYCLIPBOARD, 0, 0);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000401
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000402 /* Tell the driver to acquire the selection. The current owner
403 * will be signaled to delete it's own cache. */
404 if (~cbinfo.flags & CB_OWNER)
405 {
406 /* Assign ownership of the clipboard to the current client. We do
407 * this before acquiring the selection so that when we do acquire the
408 * selection and the selection loser gets notified, it can check if
409 * it has lost the Wine clipboard ownership. If it did then it knows
410 * that a WM_DESTORYCLIPBOARD has already been sent. Otherwise it
411 * lost the selection to a X app and it should send the
412 * WM_DESTROYCLIPBOARD itself. */
413 CLIPBOARD_SetClipboardOwner(cbinfo.hWndOpen);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000414
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000415 /* Acquire the selection. This will notify the previous owner
416 * to clear it's cache. */
417 if (USER_Driver.pAcquireClipboard)
418 USER_Driver.pAcquireClipboard(cbinfo.hWndOpen);
419 }
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000420
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000421 /* Empty the local cache */
422 if (USER_Driver.pEmptyClipboard)
423 USER_Driver.pEmptyClipboard();
424
425 bCBHasChanged = TRUE;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000426
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000427 return TRUE;
428}
429
430
431/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000432 * GetClipboardOwner (USER32.@)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000433 * FIXME: Can't return the owner if the clipboard is owned by an external X-app
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000434 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000435HWND WINAPI GetClipboardOwner(void)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000436{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000437 HWND hWndOwner = 0;
438 CLIPBOARDINFO cbinfo;
439
440 if (CLIPBOARD_GetClipboardInfo(&cbinfo))
441 hWndOwner = cbinfo.hWndOwner;
442
443 TRACE(" hWndOwner(%p)\n", hWndOwner);
444
445 return hWndOwner;
446}
447
448
449/**************************************************************************
450 * GetOpenClipboardWindow (USER32.@)
451 */
452HWND WINAPI GetOpenClipboardWindow(void)
453{
454 HWND hWndOpen = 0;
455 CLIPBOARDINFO cbinfo;
456
457 if (CLIPBOARD_GetClipboardInfo(&cbinfo))
458 hWndOpen = cbinfo.hWndOpen;
459
460 TRACE(" hWndClipWindow(%p)\n", hWndOpen);
461
462 return hWndOpen;
463}
464
465
466/**************************************************************************
467 * SetClipboardViewer (USER32.@)
468 */
469HWND WINAPI SetClipboardViewer( HWND hWnd )
470{
471 HWND hwndPrev = 0;
472
473 SERVER_START_REQ( set_clipboard_info )
474 {
475 req->flags = SET_CB_VIEWER;
476 req->viewer = WIN_GetFullHandle(hWnd);
477
478 if (wine_server_call_err( req ))
479 {
480 ERR("Failed to set clipboard.\n");
481 }
482 else
483 {
484 hwndPrev = reply->old_viewer;
485 }
486 }
487 SERVER_END_REQ;
488
489 TRACE("(%p): returning %p\n", hWnd, hwndPrev);
490
491 return hwndPrev;
492}
493
494
495/**************************************************************************
496 * GetClipboardViewer (USER32.@)
497 */
498HWND WINAPI GetClipboardViewer(void)
499{
500 HWND hWndViewer = 0;
501 CLIPBOARDINFO cbinfo;
502
503 if (CLIPBOARD_GetClipboardInfo(&cbinfo))
504 hWndViewer = cbinfo.hWndViewer;
505
506 TRACE(" hWndViewer=%p\n", hWndViewer);
507
508 return hWndViewer;
509}
510
511
512/**************************************************************************
513 * ChangeClipboardChain (USER32.@)
514 */
515BOOL WINAPI ChangeClipboardChain(HWND hWnd, HWND hWndNext)
516{
517 BOOL bRet = TRUE;
518 HWND hWndViewer = GetClipboardViewer();
519
520 if (hWndViewer)
521 {
522 if (WIN_GetFullHandle(hWnd) == hWndViewer)
523 SetClipboardViewer(WIN_GetFullHandle(hWndNext));
524 else
525 bRet = !SendMessageW(hWndViewer, WM_CHANGECBCHAIN, (WPARAM)hWnd, (LPARAM)hWndNext);
526 }
527 else
528 ERR("hWndViewer is lost\n");
529
530 return bRet;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000531}
532
533
534/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000535 * SetClipboardData (USER.141)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000536 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000537HANDLE16 WINAPI SetClipboardData16(UINT16 wFormat, HANDLE16 hData)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000538{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000539 CLIPBOARDINFO cbinfo;
540 HANDLE16 hResult = 0;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000541
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000542 TRACE("(%04X, %04x) !\n", wFormat, hData);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000543
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000544 if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
545 (~cbinfo.flags & CB_OPEN) ||
546 (~cbinfo.flags & CB_OWNER))
Noel Borthwick29700671999-09-03 15:17:57 +0000547 {
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000548 WARN("Clipboard not opened by calling task!\n");
549 }
550 else if (USER_Driver.pSetClipboardData &&
551 USER_Driver.pSetClipboardData(wFormat, hData, 0))
552 {
553 hResult = hData;
554 bCBHasChanged = TRUE;
Noel Borthwick29700671999-09-03 15:17:57 +0000555 }
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000556
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000557 return hResult;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000558}
559
Alexandre Julliard21979011997-03-05 08:22:35 +0000560
561/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000562 * SetClipboardData (USER32.@)
Alexandre Julliard21979011997-03-05 08:22:35 +0000563 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000564HANDLE WINAPI SetClipboardData(UINT wFormat, HANDLE hData)
Alexandre Julliard21979011997-03-05 08:22:35 +0000565{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000566 CLIPBOARDINFO cbinfo;
567 HANDLE hResult = 0;
Pascal Cuoq724f1901998-10-26 10:58:16 +0000568
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000569 TRACE("(%04X, %p) !\n", wFormat, hData);
Pascal Cuoq724f1901998-10-26 10:58:16 +0000570
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000571 if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
572 (~cbinfo.flags & CB_OWNER))
Noel Borthwick29700671999-09-03 15:17:57 +0000573 {
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000574 WARN("Clipboard not owned by calling task!\n");
575 }
576 else if (USER_Driver.pSetClipboardData &&
577 USER_Driver.pSetClipboardData(wFormat, 0, hData))
578 {
579 hResult = hData;
580 bCBHasChanged = TRUE;
Noel Borthwick29700671999-09-03 15:17:57 +0000581 }
Pascal Cuoq724f1901998-10-26 10:58:16 +0000582
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000583 return hResult;
Alexandre Julliard21979011997-03-05 08:22:35 +0000584}
585
Noel Borthwick29700671999-09-03 15:17:57 +0000586
Alexandre Julliard21979011997-03-05 08:22:35 +0000587/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000588 * CountClipboardFormats (USER.143)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000589 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000590INT16 WINAPI CountClipboardFormats16(void)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000591{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000592 return CountClipboardFormats();
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000593}
594
595
596/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000597 * CountClipboardFormats (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000598 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000599INT WINAPI CountClipboardFormats(void)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000600{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000601 INT count = 0;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000602
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000603 if (USER_Driver.pCountClipboardFormats)
604 count = USER_Driver.pCountClipboardFormats();
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000605
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000606 TRACE("returning %d\n", count);
607 return count;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000608}
609
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000610
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000611/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000612 * EnumClipboardFormats (USER.144)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000613 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000614UINT16 WINAPI EnumClipboardFormats16(UINT16 wFormat)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000615{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000616 return EnumClipboardFormats(wFormat);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000617}
618
619
620/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000621 * EnumClipboardFormats (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000622 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000623UINT WINAPI EnumClipboardFormats(UINT wFormat)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000624{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000625 UINT wFmt = 0;
626 CLIPBOARDINFO cbinfo;
627
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000628 TRACE("(%04X)\n", wFormat);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000629
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000630 if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
631 (~cbinfo.flags & CB_OPEN))
Noel Borthwick29700671999-09-03 15:17:57 +0000632 {
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000633 WARN("Clipboard not opened by calling task.\n");
634 SetLastError(ERROR_CLIPBOARD_NOT_OPEN);
Noel Borthwick29700671999-09-03 15:17:57 +0000635 return 0;
636 }
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000637
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000638 if (USER_Driver.pEnumClipboardFormats)
639 wFmt = USER_Driver.pEnumClipboardFormats(wFormat);
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000640
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000641 return wFmt;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000642}
643
644
645/**************************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +0000646 * IsClipboardFormatAvailable (USER.193)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000647 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000648BOOL16 WINAPI IsClipboardFormatAvailable16(UINT16 wFormat)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000649{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000650 return IsClipboardFormatAvailable(wFormat);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000651}
652
653
654/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000655 * IsClipboardFormatAvailable (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000656 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000657BOOL WINAPI IsClipboardFormatAvailable(UINT wFormat)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000658{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000659 BOOL bret = FALSE;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000660
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000661 if (USER_Driver.pIsClipboardFormatAvailable)
662 bret = USER_Driver.pIsClipboardFormatAvailable(wFormat);
663
664 TRACE("%04x, returning %d\n", wFormat, bret);
665 return bret;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000666}
667
668
669/**************************************************************************
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000670 * GetClipboardData (USER.142)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000671 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000672HANDLE16 WINAPI GetClipboardData16(UINT16 wFormat)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000673{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000674 HANDLE16 hData = 0;
675 CLIPBOARDINFO cbinfo;
676
677 if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
678 (~cbinfo.flags & CB_OPEN))
679 {
680 WARN("Clipboard not opened by calling task.\n");
681 SetLastError(ERROR_CLIPBOARD_NOT_OPEN);
682 return 0;
683 }
684
685 if (USER_Driver.pGetClipboardData)
686 USER_Driver.pGetClipboardData(wFormat, &hData, NULL);
687
688 return hData;
689}
690
691
692/**************************************************************************
693 * GetClipboardData (USER32.@)
694 */
695HANDLE WINAPI GetClipboardData(UINT wFormat)
696{
697 HANDLE hData = 0;
698 CLIPBOARDINFO cbinfo;
699
700 TRACE("%04x\n", wFormat);
701
702 if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
703 (~cbinfo.flags & CB_OPEN))
704 {
705 WARN("Clipboard not opened by calling task.\n");
706 SetLastError(ERROR_CLIPBOARD_NOT_OPEN);
707 return 0;
708 }
709
710 if (USER_Driver.pGetClipboardData)
711 USER_Driver.pGetClipboardData(wFormat, NULL, &hData);
712
713 TRACE("returning %p\n", hData);
714 return hData;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000715}
716
717
718/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000719 * GetPriorityClipboardFormat (USER32.@)
Alexandre Julliard21979011997-03-05 08:22:35 +0000720 */
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000721INT WINAPI GetPriorityClipboardFormat(UINT *list, INT nCount)
Alexandre Julliard21979011997-03-05 08:22:35 +0000722{
Alexandre Julliardd23a82b2001-09-19 20:37:04 +0000723 int i;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000724
Noel Borthwick29700671999-09-03 15:17:57 +0000725 TRACE("()\n");
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000726
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000727 if(CountClipboardFormats() == 0)
728 return 0;
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000729
Alexandre Julliardd23a82b2001-09-19 20:37:04 +0000730 for (i = 0; i < nCount; i++)
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000731 if (IsClipboardFormatAvailable(list[i]))
732 return list[i];
733
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000734 return -1;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000735}
736
David Elliott44f84b52000-10-29 01:24:54 +0000737
738/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000739 * GetClipboardSequenceNumber (USER32.@)
David Elliott44f84b52000-10-29 01:24:54 +0000740 * Supported on Win2k/Win98
741 * MSDN: Windows clipboard code keeps a serial number for the clipboard
742 * for each window station. The number is incremented whenever the
743 * contents change or are emptied.
744 * If you do not have WINSTA_ACCESSCLIPBOARD then the function returns 0
745 */
746DWORD WINAPI GetClipboardSequenceNumber(VOID)
747{
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000748 CLIPBOARDINFO cbinfo;
749
750 if (!CLIPBOARD_GetClipboardInfo(&cbinfo))
751 {
752 ERR("Failed to get clipboard information.\n");
David Elliott44f84b52000-10-29 01:24:54 +0000753 return 0;
Ulrich Czekallab2df5f92003-06-23 23:02:02 +0000754 }
755
756 TRACE("returning %x\n", cbinfo.seqno);
757 return cbinfo.seqno;
David Elliott44f84b52000-10-29 01:24:54 +0000758}