blob: fc969cd3b116409070f0fab2f5c51c1fd72d1adc [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
7 *
8 * NOTES:
9 * This file contains the implementation for the WIN32 Clipboard API
10 * and Wine's internal clipboard cache.
11 * The actual contents of the clipboard are held in the clipboard cache.
12 * The internal implementation talks to a "clipboard driver" to fill or
13 * expose the cache to the native device. (Currently only the X11 and
14 * TTY clipboard driver are available)
Alexandre Julliard1e9ac791996-06-06 18:38:27 +000015 */
Alexandre Julliardfb9a9191994-03-01 19:48:04 +000016
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000017#include <stdlib.h>
Alexandre Julliardfb9a9191994-03-01 19:48:04 +000018#include <sys/types.h>
Alexandre Julliardfb9a9191994-03-01 19:48:04 +000019#include <fcntl.h>
20#include <unistd.h>
Alexandre Julliard1e9ac791996-06-06 18:38:27 +000021#include <string.h>
François Gouget44a18222000-12-19 04:53:20 +000022
Jeremy Whited3e22d92000-02-10 19:03:02 +000023#include "windef.h"
François Gouget44a18222000-12-19 04:53:20 +000024#include "winbase.h"
Jeremy Whited3e22d92000-02-10 19:03:02 +000025#include "wingdi.h"
Marcus Meissner61afa331999-02-22 10:16:00 +000026#include "winuser.h"
Marcus Meissner219cfd81999-02-24 13:05:13 +000027#include "wine/winuser16.h"
Noel Borthwick29700671999-09-03 15:17:57 +000028#include "wine/winbase16.h"
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +000029#include "heap.h"
Alexandre Julliard42d20f92000-08-10 01:16:19 +000030#include "user.h"
Alexandre Julliard37a46392001-09-12 17:19:13 +000031#include "win.h"
Alexandre Julliard234bc241994-12-10 13:02:28 +000032#include "clipboard.h"
Alexandre Julliard359f497e1999-07-04 16:02:24 +000033#include "debugtools.h"
Alexandre Julliardfb9a9191994-03-01 19:48:04 +000034
Alexandre Julliard42d20f92000-08-10 01:16:19 +000035DEFAULT_DEBUG_CHANNEL(clipboard);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000036
Alexandre Julliard1e9ac791996-06-06 18:38:27 +000037#define CF_REGFORMATBASE 0xC000
38
Patrik Stridvalle35d6361998-12-07 09:13:40 +000039/**************************************************************************
Noel Borthwick29700671999-09-03 15:17:57 +000040 * Clipboard context global variables
Alexandre Julliard1e9ac791996-06-06 18:38:27 +000041 */
42
Noel Borthwick29700671999-09-03 15:17:57 +000043static HANDLE hClipLock = 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +000044static BOOL bCBHasChanged = FALSE;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +000045
Alexandre Julliard37a46392001-09-12 17:19:13 +000046static HWND hWndClipWindow; /* window that last opened clipboard */
47static HWND hWndClipOwner; /* current clipboard owner */
48static HANDLE16 hTaskClipOwner; /* clipboard owner's task */
49static HWND hWndViewer; /* start of viewers chain */
Alexandre Julliard1e9ac791996-06-06 18:38:27 +000050
Alexandre Julliard1e9ac791996-06-06 18:38:27 +000051static WORD LastRegFormat = CF_REGFORMATBASE;
52
Noel Borthwick29700671999-09-03 15:17:57 +000053/* Clipboard cache initial data.
Gerard Patel9289a5d2000-12-22 23:26:18 +000054 * WARNING: This data ordering is dependent on the WINE_CLIPFORMAT structure
Noel Borthwick29700671999-09-03 15:17:57 +000055 * declared in clipboard.h
56 */
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +000057WINE_CLIPFORMAT ClipFormats[] = {
Alexandre Julliard42d20f92000-08-10 01:16:19 +000058 { CF_TEXT, 1, 0, "Text", 0, 0, 0, 0, NULL, &ClipFormats[1]},
59 { CF_BITMAP, 1, 0, "Bitmap", 0, 0, 0, 0, &ClipFormats[0], &ClipFormats[2]},
60 { CF_METAFILEPICT, 1, 0, "MetaFile Picture", 0, 0, 0, 0, &ClipFormats[1], &ClipFormats[3]},
61 { CF_SYLK, 1, 0, "Sylk", 0, 0, 0, 0, &ClipFormats[2], &ClipFormats[4]},
62 { CF_DIF, 1, 0, "DIF", 0, 0, 0, 0, &ClipFormats[3], &ClipFormats[5]},
63 { CF_TIFF, 1, 0, "TIFF", 0, 0, 0, 0, &ClipFormats[4], &ClipFormats[6]},
64 { CF_OEMTEXT, 1, 0, "OEM Text", 0, 0, 0, 0, &ClipFormats[5], &ClipFormats[7]},
65 { CF_DIB, 1, 0, "DIB", 0, 0, 0, 0, &ClipFormats[6], &ClipFormats[8]},
66 { CF_PALETTE, 1, 0, "Palette", 0, 0, 0, 0, &ClipFormats[7], &ClipFormats[9]},
67 { CF_PENDATA, 1, 0, "PenData", 0, 0, 0, 0, &ClipFormats[8], &ClipFormats[10]},
68 { CF_RIFF, 1, 0, "RIFF", 0, 0, 0, 0, &ClipFormats[9], &ClipFormats[11]},
69 { CF_WAVE, 1, 0, "Wave", 0, 0, 0, 0, &ClipFormats[10], &ClipFormats[12]},
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +000070 { CF_UNICODETEXT, 1, 0, "Unicode Text", 0, 0, 0, 0, &ClipFormats[11], &ClipFormats[13]},
71 { CF_OWNERDISPLAY, 1, 0, "Owner Display", 0, 0, 0, 0, &ClipFormats[12], &ClipFormats[14]},
72 { CF_DSPTEXT, 1, 0, "DSPText", 0, 0, 0, 0, &ClipFormats[13], &ClipFormats[15]},
73 { CF_DSPMETAFILEPICT, 1, 0, "DSPMetaFile Picture", 0, 0, 0, 0, &ClipFormats[14], &ClipFormats[16]},
74 { CF_DSPBITMAP, 1, 0, "DSPBitmap", 0, 0, 0, 0, &ClipFormats[15], &ClipFormats[17]},
75 { CF_HDROP, 1, 0, "HDROP", 0, 0, 0, 0, &ClipFormats[16], NULL}
Alexandre Julliard42d20f92000-08-10 01:16:19 +000076};
Alexandre Julliardfb9a9191994-03-01 19:48:04 +000077
Noel Borthwick29700671999-09-03 15:17:57 +000078
79/**************************************************************************
80 * Internal Clipboard implementation methods
81 **************************************************************************/
82
83
84/**************************************************************************
85 * CLIPBOARD_LookupFormat
86 */
Alexandre Julliarda3960291999-02-26 11:11:13 +000087static LPWINE_CLIPFORMAT __lookup_format( LPWINE_CLIPFORMAT lpFormat, WORD wID )
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +000088{
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +000089 while(TRUE)
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +000090 {
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +000091 if (lpFormat == NULL ||
92 lpFormat->wFormatID == wID) break;
93 lpFormat = lpFormat->NextFormat;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +000094 }
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +000095 return lpFormat;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +000096}
97
Noel Borthwick29700671999-09-03 15:17:57 +000098LPWINE_CLIPFORMAT CLIPBOARD_LookupFormat( WORD wID )
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +000099{
Noel Borthwick29700671999-09-03 15:17:57 +0000100 return __lookup_format( ClipFormats, wID );
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000101}
102
Noel Borthwick29700671999-09-03 15:17:57 +0000103/**************************************************************************
104 * CLIPBOARD_IsLocked
105 * Check if the clipboard cache is available to the caller
106 */
107BOOL CLIPBOARD_IsLocked()
108{
109 BOOL bIsLocked = TRUE;
110 HANDLE16 hTaskCur = GetCurrentTask();
111
112 /*
113 * The clipboard is available:
114 * 1. if the caller's task has opened the clipboard,
115 * or
116 * 2. if the caller is the clipboard owners task, AND is responding to a
117 * WM_RENDERFORMAT message.
118 */
119 if ( hClipLock == hTaskCur )
120 bIsLocked = FALSE;
121
122 else if ( hTaskCur == hTaskClipOwner )
123 {
124 /* Check if we're currently executing inside a window procedure
125 * called in response to a WM_RENDERFORMAT message. A WM_RENDERFORMAT
126 * handler is not permitted to open the clipboard since it has been opened
127 * by another client. However the handler must have access to the
128 * clipboard in order to update data in response to this message.
129 */
Alexandre Julliard51ab43b2001-05-18 22:51:56 +0000130#if 0
Alexandre Julliard8afe6622001-07-26 20:12:22 +0000131 MESSAGEQUEUE *queue = QUEUE_Current();
Noel Borthwick29700671999-09-03 15:17:57 +0000132
133 if ( queue
134 && queue->smWaiting
135 && queue->smWaiting->msg == WM_RENDERFORMAT
136 && queue->smWaiting->hSrcQueue
137 )
138 bIsLocked = FALSE;
Alexandre Julliard51ab43b2001-05-18 22:51:56 +0000139#else
140 /* FIXME: queue check no longer possible */
141 bIsLocked = FALSE;
142#endif
Noel Borthwick29700671999-09-03 15:17:57 +0000143 }
144
145 return bIsLocked;
146}
147
148/**************************************************************************
149 * CLIPBOARD_ReleaseOwner
150 * Gives up ownership of the clipboard
151 */
152void CLIPBOARD_ReleaseOwner()
153{
154 hWndClipOwner = 0;
155 hTaskClipOwner = 0;
156}
157
158/**************************************************************************
159 * CLIPBOARD_GlobalFreeProc
160 *
161 * This is a callback mechanism to allow HGLOBAL data to be released in
162 * the context of the process which allocated it. We post a WM_TIMER message
163 * to the owner window(in CLIPBOARD_DeleteRecord) and destroy the data(in idEvent)
164 * in this WndProc, which is invoked when the apps message loop calls DispatchMessage.
165 * This technique is discussed in Matt Pietrek's "Under the Hood".
166 * An article describing the same may be found in MSDN by searching for WM_TIMER.
167 * Note that this mechanism will probably stop working when WINE supports
168 * address space separation. When "queue events" are implemented in Wine we
169 * should switch to using that mechanism, since it is more robust and does not
170 * require a procedure address to be passed. See the SetWinEventHook API for
171 * more info on this.
172 */
173VOID CALLBACK CLIPBOARD_GlobalFreeProc( HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime )
174{
175 /* idEvent is the HGLOBAL to be deleted */
176 GlobalFree( (HGLOBAL)idEvent );
177}
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000178
179/**************************************************************************
180 * CLIPBOARD_DeleteRecord
181 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000182void CLIPBOARD_DeleteRecord(LPWINE_CLIPFORMAT lpFormat, BOOL bChange)
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000183{
Alexandre Julliard03468f71998-02-15 19:40:49 +0000184 if( (lpFormat->wFormatID >= CF_GDIOBJFIRST &&
Ulrich Czekalla6623b851999-10-23 14:10:04 +0000185 lpFormat->wFormatID <= CF_GDIOBJLAST) || lpFormat->wFormatID == CF_BITMAP
186 || lpFormat->wFormatID == CF_PALETTE)
Alexandre Julliard03468f71998-02-15 19:40:49 +0000187 {
Pascal Cuoq724f1901998-10-26 10:58:16 +0000188 if (lpFormat->hData32)
Alexandre Julliarda3960291999-02-26 11:11:13 +0000189 DeleteObject(lpFormat->hData32);
Pascal Cuoq724f1901998-10-26 10:58:16 +0000190 if (lpFormat->hData16)
Alexandre Julliardb0efe282000-08-04 04:18:04 +0000191 DeleteObject(lpFormat->hData16);
Alexandre Julliard03468f71998-02-15 19:40:49 +0000192 }
Pascal Cuoq724f1901998-10-26 10:58:16 +0000193 else if( lpFormat->wFormatID == CF_METAFILEPICT )
194 {
195 if (lpFormat->hData32)
196 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000197 DeleteMetaFile( ((METAFILEPICT *)GlobalLock( lpFormat->hData32 ))->hMF );
Noel Borthwick29700671999-09-03 15:17:57 +0000198 PostMessageA(hWndClipOwner, WM_TIMER,
199 (WPARAM)lpFormat->hData32, (LPARAM)CLIPBOARD_GlobalFreeProc);
Noel Borthwick83579c81999-07-24 12:18:04 +0000200 if (lpFormat->hDataSrc32)
Noel Borthwick29700671999-09-03 15:17:57 +0000201 {
202 /* Release lpFormat->hData32 in the context of the process which created it.
203 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
204 * GlobalFree(lpFormat->hDataSrc32);
205 */
206 PostMessageA(hWndClipOwner, WM_TIMER,
207 (WPARAM)lpFormat->hDataSrc32, (LPARAM)CLIPBOARD_GlobalFreeProc);
208 }
209
Pascal Cuoq724f1901998-10-26 10:58:16 +0000210 if (lpFormat->hData16)
211 /* HMETAFILE16 and HMETAFILE32 are apparently the same thing,
212 and a shallow copy is enough to share a METAFILEPICT
213 structure between 16bit and 32bit clipboards. The MetaFile
214 should of course only be deleted once. */
215 GlobalFree16(lpFormat->hData16);
216 }
Noel Borthwick83579c81999-07-24 12:18:04 +0000217 if (lpFormat->hData16)
Pascal Cuoq724f1901998-10-26 10:58:16 +0000218 {
219 DeleteMetaFile16( ((METAFILEPICT16 *)GlobalLock16( lpFormat->hData16 ))->hMF );
220 GlobalFree16(lpFormat->hData16);
221 }
222 }
223 else
224 {
225 if (lpFormat->hData32)
Noel Borthwick29700671999-09-03 15:17:57 +0000226 {
227 /* Release lpFormat->hData32 in the context of the process which created it.
228 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
229 * GlobalFree( lpFormat->hData32 );
230 */
231 PostMessageA(hWndClipOwner, WM_TIMER,
232 (WPARAM)lpFormat->hData32, (LPARAM)CLIPBOARD_GlobalFreeProc);
233 }
Noel Borthwick83579c81999-07-24 12:18:04 +0000234 if (lpFormat->hDataSrc32)
Noel Borthwick29700671999-09-03 15:17:57 +0000235 {
236 /* Release lpFormat->hData32 in the context of the process which created it.
237 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
238 * GlobalFree(lpFormat->hDataSrc32);
239 */
240 PostMessageA(hWndClipOwner, WM_TIMER,
241 (WPARAM)lpFormat->hDataSrc32, (LPARAM)CLIPBOARD_GlobalFreeProc);
242 }
Pascal Cuoq724f1901998-10-26 10:58:16 +0000243 if (lpFormat->hData16)
244 GlobalFree16(lpFormat->hData16);
245 }
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000246
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000247 lpFormat->wDataPresent = 0;
Pascal Cuoq724f1901998-10-26 10:58:16 +0000248 lpFormat->hData16 = 0;
249 lpFormat->hData32 = 0;
Noel Borthwick29700671999-09-03 15:17:57 +0000250 lpFormat->hDataSrc32 = 0;
251 lpFormat->drvData = 0;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000252
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000253 if( bChange ) bCBHasChanged = TRUE;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000254}
255
256/**************************************************************************
Noel Borthwick29700671999-09-03 15:17:57 +0000257 * CLIPBOARD_EmptyCache
258 */
259void CLIPBOARD_EmptyCache( BOOL bChange )
260{
261 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
262
263 while(lpFormat)
264 {
265 if ( lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32 )
266 CLIPBOARD_DeleteRecord( lpFormat, bChange );
267
268 lpFormat = lpFormat->NextFormat;
269 }
270}
271
272/**************************************************************************
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000273 * CLIPBOARD_IsPresent
274 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000275BOOL CLIPBOARD_IsPresent(WORD wFormat)
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000276{
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000277 /* special case */
278
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000279 if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT || wFormat == CF_UNICODETEXT )
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000280 return ClipFormats[CF_TEXT-1].wDataPresent ||
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000281 ClipFormats[CF_OEMTEXT-1].wDataPresent ||
282 ClipFormats[CF_UNICODETEXT-1].wDataPresent;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000283 else
284 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000285 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000286 if( lpFormat ) return (lpFormat->wDataPresent);
287 }
288 return FALSE;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000289}
290
291/**************************************************************************
Noel Borthwick29700671999-09-03 15:17:57 +0000292 * CLIPBOARD_IsCacheRendered
293 * Checks if any data needs to be rendered to the clipboard cache
294 * RETURNS:
295 * TRUE - All clipboard data is available in the cache
296 * FALSE - Some data is marked for delayed render and needs rendering
297 */
298BOOL CLIPBOARD_IsCacheRendered()
299{
300 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
301
302 /* check if all formats were rendered */
303 while(lpFormat)
304 {
305 if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
306 return FALSE;
307
308 lpFormat = lpFormat->NextFormat;
309 }
310
311 return TRUE;
312}
313
314
315/**************************************************************************
Noel Borthwick83579c81999-07-24 12:18:04 +0000316 * CLIPBOARD_IsMemoryObject
317 * Tests if the clipboard format specifies a memory object
318 */
319BOOL CLIPBOARD_IsMemoryObject( WORD wFormat )
320{
321 switch(wFormat)
322 {
323 case CF_BITMAP:
324 case CF_METAFILEPICT:
325 case CF_DSPTEXT:
326 case CF_ENHMETAFILE:
327 case CF_HDROP:
328 case CF_PALETTE:
329 case CF_PENDATA:
330 return FALSE;
331 default:
332 return TRUE;
333 }
334}
335
336/***********************************************************************
337 * CLIPBOARD_GlobalDupMem( HGLOBAL )
338 * Helper method to duplicate an HGLOBAL chunk of memory into shared memory
339 */
340HGLOBAL CLIPBOARD_GlobalDupMem( HGLOBAL hGlobalSrc )
341{
342 HGLOBAL hGlobalDest;
343 PVOID pGlobalSrc, pGlobalDest;
344 DWORD cBytes;
345
346 if ( !hGlobalSrc )
347 return 0;
348
349 cBytes = GlobalSize(hGlobalSrc);
350 if ( 0 == cBytes )
351 return 0;
352
353 /* Turn on the DDESHARE and _MOVEABLE flags explicitly */
354 hGlobalDest = GlobalAlloc( GlobalFlags(hGlobalSrc) | GMEM_DDESHARE | GMEM_MOVEABLE,
355 cBytes );
356 if ( !hGlobalDest )
357 return 0;
358
359 pGlobalSrc = GlobalLock(hGlobalSrc);
360 pGlobalDest = GlobalLock(hGlobalDest);
361 if ( !pGlobalSrc || !pGlobalDest )
362 return 0;
363
364 memcpy(pGlobalDest, pGlobalSrc, cBytes);
365
366 GlobalUnlock(hGlobalSrc);
367 GlobalUnlock(hGlobalDest);
368
369 return hGlobalDest;
370}
371
372/**************************************************************************
Noel Borthwick29700671999-09-03 15:17:57 +0000373 * CLIPBOARD_GetFormatName
374 * Gets the format name associated with an ID
375 */
376char * CLIPBOARD_GetFormatName(UINT wFormat)
377{
378 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
379 return (lpFormat) ? lpFormat->Name : NULL;
380}
381
382
383/**************************************************************************
384 * CLIPBOARD_RenderFormat
385 */
386static BOOL CLIPBOARD_RenderFormat(LPWINE_CLIPFORMAT lpFormat)
387{
388 /*
389 * If WINE is not the selection owner, and the format is available
Gerard Patel9289a5d2000-12-22 23:26:18 +0000390 * we must ask the driver to render the data to the clipboard cache.
Noel Borthwick29700671999-09-03 15:17:57 +0000391 */
Gerard Patel9289a5d2000-12-22 23:26:18 +0000392 TRACE("enter format=%d\n", lpFormat->wFormatID);
Alexandre Julliard42d20f92000-08-10 01:16:19 +0000393 if ( !USER_Driver.pIsSelectionOwner()
394 && USER_Driver.pIsClipboardFormatAvailable( lpFormat->wFormatID ) )
Noel Borthwick29700671999-09-03 15:17:57 +0000395 {
Alexandre Julliard42d20f92000-08-10 01:16:19 +0000396 if ( !USER_Driver.pGetClipboardData( lpFormat->wFormatID ) )
Noel Borthwick29700671999-09-03 15:17:57 +0000397 return FALSE;
398 }
399 /*
400 * If Wine owns the clipboard, and the data is marked for delayed render,
401 * render it now.
402 */
403 else if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
404 {
405 if( IsWindow(hWndClipOwner) )
406 {
407 /* Send a WM_RENDERFORMAT message to notify the owner to render the
408 * data requested into the clipboard.
409 */
410 TRACE("Sending WM_RENDERFORMAT message\n");
Alexandre Julliardcb25e252001-08-08 23:28:42 +0000411 SendMessageW( hWndClipOwner, WM_RENDERFORMAT, (WPARAM)lpFormat->wFormatID, 0 );
Noel Borthwick29700671999-09-03 15:17:57 +0000412 }
413 else
414 {
415 WARN("\thWndClipOwner (%04x) is lost!\n",
416 hWndClipOwner);
417 CLIPBOARD_ReleaseOwner();
418 lpFormat->wDataPresent = 0;
419 return FALSE;
420 }
421 }
422
423 return (lpFormat->hData16 || lpFormat->hData32) ? TRUE : FALSE;
424}
425
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000426/**************************************************************************
427 * CLIPBOARD_ConvertText
428 * Returns number of required/converted characters - not bytes!
429 */
430static INT CLIPBOARD_ConvertText(WORD src_fmt, void const *src, INT src_size,
431 WORD dst_fmt, void *dst, INT dst_size)
432{
433 UINT cp;
434
435 if(src_fmt == CF_UNICODETEXT)
436 {
437 switch(dst_fmt)
438 {
439 case CF_TEXT:
440 cp = CP_ACP;
441 break;
442 case CF_OEMTEXT:
443 cp = CP_OEMCP;
444 break;
445 default:
446 return 0;
447 }
448 return WideCharToMultiByte(cp, 0, src, src_size, dst, dst_size, NULL, NULL);
449 }
450
451 if(dst_fmt == CF_UNICODETEXT)
452 {
453 switch(src_fmt)
454 {
455 case CF_TEXT:
456 cp = CP_ACP;
457 break;
458 case CF_OEMTEXT:
459 cp = CP_OEMCP;
460 break;
461 default:
462 return 0;
463 }
464 return MultiByteToWideChar(cp, 0, src, src_size, dst, dst_size);
465 }
466
467 if(!dst_size) return src_size;
468
469 if(dst_size > src_size) dst_size = src_size;
470
471 if(src_fmt == CF_TEXT )
472 CharToOemBuffA(src, dst, dst_size);
473 else
474 OemToCharBuffA(src, dst, dst_size);
475
476 return dst_size;
477}
Noel Borthwick29700671999-09-03 15:17:57 +0000478
479/**************************************************************************
480 * CLIPBOARD_RenderText
481 *
482 * Renders text to the clipboard buffer converting between UNIX and DOS formats.
483 *
484 * RETURNS: pointer to the WINE_CLIPFORMAT if successful, NULL otherwise
485 *
486 * FIXME: Should be a pair of driver functions that convert between OEM text and Windows.
487 *
488 */
489static LPWINE_CLIPFORMAT CLIPBOARD_RenderText( UINT wFormat )
490{
491 LPWINE_CLIPFORMAT lpSource = ClipFormats;
Gerard Patel9289a5d2000-12-22 23:26:18 +0000492 LPWINE_CLIPFORMAT lpTarget = NULL;
493 BOOL foundData = FALSE;
494
Aric Stewart039ae272001-02-12 19:16:05 +0000495 /* Asked for CF_TEXT */
496 if( wFormat == CF_TEXT)
Noel Borthwick29700671999-09-03 15:17:57 +0000497 {
Aric Stewart039ae272001-02-12 19:16:05 +0000498 if(ClipFormats[CF_TEXT-1].wDataPresent)
499 {
500 lpSource = &ClipFormats[CF_TEXT-1];
501 lpTarget = &ClipFormats[CF_TEXT-1];
502 foundData = TRUE;
503 TRACE("\t TEXT -> TEXT\n");
504 }
505 else if(ClipFormats[CF_UNICODETEXT-1].wDataPresent)
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000506 {
507 /* Convert UNICODETEXT -> TEXT */
508 lpSource = &ClipFormats[CF_UNICODETEXT-1];
509 lpTarget = &ClipFormats[CF_TEXT-1];
Gerard Patel9289a5d2000-12-22 23:26:18 +0000510 foundData = TRUE;
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000511 TRACE("\tUNICODETEXT -> TEXT\n");
512 }
513 else if(ClipFormats[CF_OEMTEXT-1].wDataPresent)
514 {
515 /* Convert OEMTEXT -> TEXT */
516 lpSource = &ClipFormats[CF_OEMTEXT-1];
517 lpTarget = &ClipFormats[CF_TEXT-1];
Gerard Patel9289a5d2000-12-22 23:26:18 +0000518 foundData = TRUE;
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000519 TRACE("\tOEMTEXT -> TEXT\n");
520 }
Noel Borthwick29700671999-09-03 15:17:57 +0000521 }
Aric Stewart039ae272001-02-12 19:16:05 +0000522 /* Asked for CF_OEMTEXT */
523 else if( wFormat == CF_OEMTEXT)
Noel Borthwick29700671999-09-03 15:17:57 +0000524 {
Aric Stewart039ae272001-02-12 19:16:05 +0000525 if(ClipFormats[CF_OEMTEXT-1].wDataPresent)
526 {
527 lpSource = &ClipFormats[CF_OEMTEXT-1];
528 lpTarget = &ClipFormats[CF_OEMTEXT-1];
529 foundData = TRUE;
530 TRACE("\tOEMTEXT -> OEMTEXT\n");
531 }
532 else if(ClipFormats[CF_UNICODETEXT-1].wDataPresent)
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000533 {
534 /* Convert UNICODETEXT -> OEMTEXT */
535 lpSource = &ClipFormats[CF_UNICODETEXT-1];
536 lpTarget = &ClipFormats[CF_OEMTEXT-1];
Gerard Patel9289a5d2000-12-22 23:26:18 +0000537 foundData = TRUE;
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000538 TRACE("\tUNICODETEXT -> OEMTEXT\n");
539 }
540 else if(ClipFormats[CF_TEXT-1].wDataPresent)
541 {
542 /* Convert TEXT -> OEMTEXT */
543 lpSource = &ClipFormats[CF_TEXT-1];
544 lpTarget = &ClipFormats[CF_OEMTEXT-1];
Gerard Patel9289a5d2000-12-22 23:26:18 +0000545 foundData = TRUE;
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000546 TRACE("\tTEXT -> OEMTEXT\n");
547 }
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000548 }
Aric Stewart039ae272001-02-12 19:16:05 +0000549 /* Asked for CF_UNICODETEXT */
550 else if( wFormat == CF_UNICODETEXT )
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000551 {
Aric Stewart039ae272001-02-12 19:16:05 +0000552 if(ClipFormats[CF_UNICODETEXT-1].wDataPresent)
553 {
554 lpSource = &ClipFormats[CF_UNICODETEXT-1];
555 lpTarget = &ClipFormats[CF_UNICODETEXT-1];
556 foundData = TRUE;
557 TRACE("\tUNICODETEXT -> UNICODETEXT\n");
558 }
559 else if(ClipFormats[CF_TEXT-1].wDataPresent)
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000560 {
561 /* Convert TEXT -> UNICODETEXT */
562 lpSource = &ClipFormats[CF_TEXT-1];
563 lpTarget = &ClipFormats[CF_UNICODETEXT-1];
Gerard Patel9289a5d2000-12-22 23:26:18 +0000564 foundData = TRUE;
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000565 TRACE("\tTEXT -> UNICODETEXT\n");
566 }
567 else if(ClipFormats[CF_OEMTEXT-1].wDataPresent)
568 {
569 /* Convert OEMTEXT -> UNICODETEXT */
570 lpSource = &ClipFormats[CF_OEMTEXT-1];
571 lpTarget = &ClipFormats[CF_UNICODETEXT-1];
Gerard Patel9289a5d2000-12-22 23:26:18 +0000572 foundData = TRUE;
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000573 TRACE("\tOEMTEXT -> UNICODETEXT\n");
574 }
Noel Borthwick29700671999-09-03 15:17:57 +0000575 }
Gerard Patel9289a5d2000-12-22 23:26:18 +0000576 if (!foundData)
577 {
578 if ((wFormat == CF_TEXT) || (wFormat == CF_OEMTEXT))
579 {
580 lpSource = &ClipFormats[CF_UNICODETEXT-1];
581 lpTarget = __lookup_format( ClipFormats, wFormat );
582 }
583 else
584 {
585 lpSource = __lookup_format( ClipFormats, wFormat );
586 lpTarget = lpSource;
587 }
Noel Borthwick29700671999-09-03 15:17:57 +0000588 }
589
590 /* First render the source text format */
591 if ( !lpSource || !CLIPBOARD_RenderFormat(lpSource) ) return NULL;
592
593 /* Convert to the desired target text format, if necessary */
594 if( lpTarget != lpSource && !lpTarget->hData16 && !lpTarget->hData32 )
595 {
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000596 INT src_chars, dst_chars, alloc_size;
Noel Borthwick29700671999-09-03 15:17:57 +0000597 LPCSTR lpstrS;
598 LPSTR lpstrT;
599
600 if (lpSource->hData32)
601 {
Noel Borthwick29700671999-09-03 15:17:57 +0000602 lpstrS = (LPSTR)GlobalLock(lpSource->hData32);
603 }
604 else
605 {
Noel Borthwick29700671999-09-03 15:17:57 +0000606 lpstrS = (LPSTR)GlobalLock16(lpSource->hData16);
607 }
608
609 if( !lpstrS ) return NULL;
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000610
611 /* Text always NULL terminated */
612 if(lpSource->wFormatID == CF_UNICODETEXT)
Aric Stewart096c1ae2001-02-20 01:54:08 +0000613 src_chars = strlenW((LPCWSTR)lpstrS)+1;
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000614 else
Aric Stewart096c1ae2001-02-20 01:54:08 +0000615 src_chars = strlen(lpstrS)+1;
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000616
617 /* Calculate number of characters in the destination buffer */
618 dst_chars = CLIPBOARD_ConvertText(lpSource->wFormatID, lpstrS, src_chars,
619 lpTarget->wFormatID, NULL, 0);
620 if(!dst_chars) return NULL;
621
Noel Borthwick29700671999-09-03 15:17:57 +0000622 TRACE("\tconverting from '%s' to '%s', %i chars\n",
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000623 lpSource->Name, lpTarget->Name, src_chars);
624
625 /* Convert characters to bytes */
626 if(lpTarget->wFormatID == CF_UNICODETEXT)
627 alloc_size = dst_chars * sizeof(WCHAR);
628 else
629 alloc_size = dst_chars;
630
631 lpTarget->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, alloc_size);
Noel Borthwick29700671999-09-03 15:17:57 +0000632 lpstrT = (LPSTR)GlobalLock(lpTarget->hData32);
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000633
Noel Borthwick29700671999-09-03 15:17:57 +0000634 if( lpstrT )
635 {
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000636 CLIPBOARD_ConvertText(lpSource->wFormatID, lpstrS, src_chars,
637 lpTarget->wFormatID, lpstrT, dst_chars);
Noel Borthwick29700671999-09-03 15:17:57 +0000638 GlobalUnlock(lpTarget->hData32);
639 }
640 else
641 lpTarget->hData32 = 0;
642
643 /* Unlock source */
644 if (lpSource->hData32)
645 GlobalUnlock(lpSource->hData32);
646 else
647 GlobalUnlock16(lpSource->hData16);
648 }
649
650 return (lpTarget->hData16 || lpTarget->hData32) ? lpTarget : NULL;
651}
652
653/**************************************************************************
Gerard Patel9289a5d2000-12-22 23:26:18 +0000654 * CLIPBOARD_EnumClipboardFormats (internal)
655 */
656static UINT CLIPBOARD_EnumClipboardFormats( UINT wFormat )
657{
658 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
659 BOOL bFormatPresent;
660
661 if (wFormat == 0) /* start from the beginning */
662 lpFormat = ClipFormats;
663 else
664 {
665 /* walk up to the specified format record */
666
667 if( !(lpFormat = __lookup_format( lpFormat, wFormat )) )
668 return 0;
669 lpFormat = lpFormat->NextFormat; /* right */
670 }
671
672 while(TRUE)
673 {
674 if (lpFormat == NULL) return 0;
675
676 if(CLIPBOARD_IsPresent(lpFormat->wFormatID))
677 break;
678
679 /* Query the driver if not yet in the cache */
680 if (!USER_Driver.pIsSelectionOwner())
681 {
682 if(lpFormat->wFormatID == CF_UNICODETEXT ||
683 lpFormat->wFormatID == CF_TEXT ||
684 lpFormat->wFormatID == CF_OEMTEXT)
685 {
686 if(USER_Driver.pIsClipboardFormatAvailable(CF_UNICODETEXT) ||
687 USER_Driver.pIsClipboardFormatAvailable(CF_TEXT) ||
688 USER_Driver.pIsClipboardFormatAvailable(CF_OEMTEXT))
689 bFormatPresent = TRUE;
690 else
691 bFormatPresent = FALSE;
692 }
693 else
694 bFormatPresent = USER_Driver.pIsClipboardFormatAvailable(lpFormat->wFormatID);
695
696 if(bFormatPresent)
697 break;
698 }
699
700 lpFormat = lpFormat->NextFormat;
701 }
702
703 TRACE("Next available format %d\n", lpFormat->wFormatID);
704
705 return lpFormat->wFormatID;
706}
707
708
709/**************************************************************************
Noel Borthwick29700671999-09-03 15:17:57 +0000710 * WIN32 Clipboard implementation
711 **************************************************************************/
712
713/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000714 * OpenClipboard (USER32.@)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000715 *
716 * Note: Netscape uses NULL hWnd to open the clipboard.
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000717 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000718BOOL WINAPI OpenClipboard( HWND hWnd )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000719{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000720 BOOL bRet;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000721
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000722 TRACE("(%04x)...\n", hWnd);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000723
Noel Borthwick29700671999-09-03 15:17:57 +0000724 if (!hClipLock)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000725 {
Noel Borthwick29700671999-09-03 15:17:57 +0000726 hClipLock = GetCurrentTask();
727
728 /* Save current user of the clipboard */
Alexandre Julliard37a46392001-09-12 17:19:13 +0000729 hWndClipWindow = WIN_GetFullHandle( hWnd );
Noel Borthwick29700671999-09-03 15:17:57 +0000730 bCBHasChanged = FALSE;
731 bRet = TRUE;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000732 }
733 else bRet = FALSE;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000734
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000735 TRACE(" returning %i\n", bRet);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000736 return bRet;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000737}
738
739
740/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000741 * CloseClipboard (USER.138)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000742 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000743BOOL16 WINAPI CloseClipboard16(void)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000744{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000745 return CloseClipboard();
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000746}
747
748
749/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000750 * CloseClipboard (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000751 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000752BOOL WINAPI CloseClipboard(void)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000753{
Noel Borthwick29700671999-09-03 15:17:57 +0000754 TRACE("()\n");
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000755
Noel Borthwick29700671999-09-03 15:17:57 +0000756 if (hClipLock == GetCurrentTask())
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000757 {
758 hWndClipWindow = 0;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000759
Alexandre Julliardcb25e252001-08-08 23:28:42 +0000760 if (bCBHasChanged && hWndViewer) SendMessageW( hWndViewer, WM_DRAWCLIPBOARD, 0, 0 );
Noel Borthwick29700671999-09-03 15:17:57 +0000761 hClipLock = 0;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000762 }
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000763 return TRUE;
764}
765
766
767/**************************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +0000768 * EmptyClipboard (USER.139)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000769 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000770BOOL16 WINAPI EmptyClipboard16(void)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000771{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000772 return EmptyClipboard();
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000773}
774
775
776/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000777 * EmptyClipboard (USER32.@)
Noel Borthwick29700671999-09-03 15:17:57 +0000778 * Empties and acquires ownership of the clipboard
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000779 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000780BOOL WINAPI EmptyClipboard(void)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000781{
Noel Borthwick29700671999-09-03 15:17:57 +0000782 TRACE("()\n");
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000783
Noel Borthwick29700671999-09-03 15:17:57 +0000784 if (hClipLock != GetCurrentTask())
785 {
Francois Gougete76218d2001-05-09 17:31:31 +0000786 WARN("Clipboard not opened by calling task!\n");
Noel Borthwick29700671999-09-03 15:17:57 +0000787 return FALSE;
788 }
789
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000790 /* destroy private objects */
791
Alexandre Julliardcb25e252001-08-08 23:28:42 +0000792 if (hWndClipOwner) SendMessageW( hWndClipOwner, WM_DESTROYCLIPBOARD, 0, 0 );
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000793
Noel Borthwick29700671999-09-03 15:17:57 +0000794 /* empty the cache */
795 CLIPBOARD_EmptyCache(TRUE);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000796
Noel Borthwick29700671999-09-03 15:17:57 +0000797 /* Assign ownership of the clipboard to the current client */
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000798 hWndClipOwner = hWndClipWindow;
799
Noel Borthwick29700671999-09-03 15:17:57 +0000800 /* Save the current task */
801 hTaskClipOwner = GetCurrentTask();
802
803 /* Tell the driver to acquire the selection */
Alexandre Julliard42d20f92000-08-10 01:16:19 +0000804 USER_Driver.pAcquireClipboard();
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000805
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000806 return TRUE;
807}
808
809
810/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000811 * GetClipboardOwner (USER32.@)
Noel Borthwick29700671999-09-03 15:17:57 +0000812 * FIXME: Can't return the owner if the clipbard is owned by an external app
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000813 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000814HWND WINAPI GetClipboardOwner(void)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000815{
Noel Borthwick29700671999-09-03 15:17:57 +0000816 TRACE("()\n");
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000817 return hWndClipOwner;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000818}
819
820
821/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000822 * SetClipboardData (USER.141)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000823 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000824HANDLE16 WINAPI SetClipboardData16( UINT16 wFormat, HANDLE16 hData )
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000825{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000826 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000827
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000828 TRACE("(%04X, %04x) !\n", wFormat, hData);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000829
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000830 /* NOTE: If the hData is zero and current owner doesn't match
831 * the window that opened the clipboard then this application
Noel Borthwick29700671999-09-03 15:17:57 +0000832 * is screwed because WM_RENDERFORMAT will go to the owner.
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000833 * (to become the owner it must call EmptyClipboard() before
834 * adding new data).
835 */
836
Noel Borthwick29700671999-09-03 15:17:57 +0000837 if( CLIPBOARD_IsLocked() || !lpFormat ||
838 (!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) )
839 {
Juergen Schmied1c35dae2000-02-07 16:22:57 +0000840 WARN("Invalid hData or clipboard not opened by calling task!\n");
Noel Borthwick29700671999-09-03 15:17:57 +0000841 return 0;
842 }
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000843
Noel Borthwick29700671999-09-03 15:17:57 +0000844 /* Pass on the request to the driver */
Alexandre Julliard42d20f92000-08-10 01:16:19 +0000845 USER_Driver.pSetClipboardData(wFormat);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000846
Pascal Cuoq724f1901998-10-26 10:58:16 +0000847 if ( lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32 )
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000848 {
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000849 CLIPBOARD_DeleteRecord(lpFormat, TRUE);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000850
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000851 /* delete existing CF_UNICODETEXT/CF_TEXT/CF_OEMTEXT aliases */
852 if(wFormat == CF_UNICODETEXT)
853 {
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000854 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000855 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
856 }
857 else if(wFormat == CF_TEXT)
858 {
859 CLIPBOARD_DeleteRecord(&ClipFormats[CF_UNICODETEXT-1], TRUE);
860 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
861 }
862 else if(wFormat == CF_OEMTEXT)
863 {
864 CLIPBOARD_DeleteRecord(&ClipFormats[CF_UNICODETEXT-1], TRUE);
865 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
866 }
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000867 }
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000868
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000869 bCBHasChanged = TRUE;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000870 lpFormat->wDataPresent = 1;
Pascal Cuoq724f1901998-10-26 10:58:16 +0000871 lpFormat->hData16 = hData; /* 0 is legal, see WM_RENDERFORMAT */
872 lpFormat->hData32 = 0;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000873
Pascal Cuoq724f1901998-10-26 10:58:16 +0000874 return lpFormat->hData16;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000875}
876
Alexandre Julliard21979011997-03-05 08:22:35 +0000877
878/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000879 * SetClipboardData (USER32.@)
Alexandre Julliard21979011997-03-05 08:22:35 +0000880 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000881HANDLE WINAPI SetClipboardData( UINT wFormat, HANDLE hData )
Alexandre Julliard21979011997-03-05 08:22:35 +0000882{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000883 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
Pascal Cuoq724f1901998-10-26 10:58:16 +0000884
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000885 TRACE("(%08X, %08x) !\n", wFormat, hData);
Pascal Cuoq724f1901998-10-26 10:58:16 +0000886
887 /* NOTE: If the hData is zero and current owner doesn't match
888 * the window that opened the clipboard then this application
Noel Borthwick29700671999-09-03 15:17:57 +0000889 * is screwed because WM_RENDERFORMAT will go to the owner.
Pascal Cuoq724f1901998-10-26 10:58:16 +0000890 * (to become the owner it must call EmptyClipboard() before
891 * adding new data).
892 */
893
Noel Borthwick29700671999-09-03 15:17:57 +0000894 if( CLIPBOARD_IsLocked() || !lpFormat ||
895 (!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) )
896 {
Juergen Schmied1c35dae2000-02-07 16:22:57 +0000897 WARN("Invalid hData or clipboard not opened by calling task!\n");
Noel Borthwick29700671999-09-03 15:17:57 +0000898 return 0;
899 }
Pascal Cuoq724f1901998-10-26 10:58:16 +0000900
Noel Borthwick29700671999-09-03 15:17:57 +0000901 /* Tell the driver to acquire the selection */
Alexandre Julliard42d20f92000-08-10 01:16:19 +0000902 USER_Driver.pAcquireClipboard();
Pascal Cuoq724f1901998-10-26 10:58:16 +0000903
Noel Borthwick29700671999-09-03 15:17:57 +0000904 if ( lpFormat->wDataPresent &&
905 (lpFormat->hData16 || lpFormat->hData32) )
Pascal Cuoq724f1901998-10-26 10:58:16 +0000906 {
907 CLIPBOARD_DeleteRecord(lpFormat, TRUE);
908
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000909 /* delete existing CF_UNICODETEXT/CF_TEXT/CF_OEMTEXT aliases */
910 if(wFormat == CF_UNICODETEXT)
911 {
Pascal Cuoq724f1901998-10-26 10:58:16 +0000912 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000913 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
914 }
915 else if(wFormat == CF_TEXT)
916 {
917 CLIPBOARD_DeleteRecord(&ClipFormats[CF_UNICODETEXT-1], TRUE);
918 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
919 }
920 else if(wFormat == CF_OEMTEXT)
921 {
922 CLIPBOARD_DeleteRecord(&ClipFormats[CF_UNICODETEXT-1], TRUE);
923 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
924 }
Pascal Cuoq724f1901998-10-26 10:58:16 +0000925 }
926
927 bCBHasChanged = TRUE;
928 lpFormat->wDataPresent = 1;
Noel Borthwick83579c81999-07-24 12:18:04 +0000929 lpFormat->hDataSrc32 = hData; /* Save the source handle */
930
931 /*
932 * Make a shared duplicate if the memory is not shared
933 * TODO: What should be done for non-memory objects
934 */
935 if ( CLIPBOARD_IsMemoryObject(wFormat) && hData && !(GlobalFlags(hData) & GMEM_DDESHARE) )
936 lpFormat->hData32 = CLIPBOARD_GlobalDupMem( hData );
937 else
Noel Borthwick29700671999-09-03 15:17:57 +0000938 lpFormat->hData32 = hData; /* 0 is legal, see WM_RENDERFORMAT */
Noel Borthwick83579c81999-07-24 12:18:04 +0000939
Pascal Cuoq724f1901998-10-26 10:58:16 +0000940 lpFormat->hData16 = 0;
941
Noel Borthwick29700671999-09-03 15:17:57 +0000942 return lpFormat->hData32; /* Should we return lpFormat->hDataSrc32 */
Alexandre Julliard21979011997-03-05 08:22:35 +0000943}
944
945
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000946/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000947 * GetClipboardData (USER.142)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000948 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000949HANDLE16 WINAPI GetClipboardData16( UINT16 wFormat )
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000950{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000951 LPWINE_CLIPFORMAT lpRender = ClipFormats;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000952
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000953 TRACE("(%04X)\n", wFormat);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000954
Noel Borthwick29700671999-09-03 15:17:57 +0000955 if (CLIPBOARD_IsLocked())
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000956 {
Juergen Schmied1c35dae2000-02-07 16:22:57 +0000957 WARN("Clipboard not opened by calling task!\n");
Noel Borthwick29700671999-09-03 15:17:57 +0000958 return 0;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000959 }
Noel Borthwick29700671999-09-03 15:17:57 +0000960
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +0000961 if( wFormat == CF_UNICODETEXT || wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000962 {
Noel Borthwick29700671999-09-03 15:17:57 +0000963 lpRender = CLIPBOARD_RenderText(wFormat);
964 if ( !lpRender ) return 0;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000965 }
966 else
967 {
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000968 lpRender = __lookup_format( ClipFormats, wFormat );
Noel Borthwick29700671999-09-03 15:17:57 +0000969 if( !lpRender || !CLIPBOARD_RenderFormat(lpRender) ) return 0;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000970 }
971
Noel Borthwick29700671999-09-03 15:17:57 +0000972 /* Convert between 32 -> 16 bit data, if necessary */
Francis Beaudet56ab55d1999-10-24 20:22:24 +0000973 if( lpRender->hData32 && !lpRender->hData16
974 && CLIPBOARD_IsMemoryObject(wFormat) )
Pascal Cuoq724f1901998-10-26 10:58:16 +0000975 {
976 int size;
Noel Borthwick29700671999-09-03 15:17:57 +0000977 if( lpRender->wFormatID == CF_METAFILEPICT )
Pascal Cuoq724f1901998-10-26 10:58:16 +0000978 size = sizeof( METAFILEPICT16 );
979 else
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000980 size = GlobalSize(lpRender->hData32);
981
Noel Borthwick29700671999-09-03 15:17:57 +0000982 lpRender->hData16 = GlobalAlloc16(GMEM_ZEROINIT, size);
983 if( !lpRender->hData16 )
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000984 ERR("(%04X) -- not enough memory in 16b heap\n", wFormat);
Pascal Cuoq724f1901998-10-26 10:58:16 +0000985 else
986 {
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000987 if( lpRender->wFormatID == CF_METAFILEPICT )
988 {
989 FIXME("\timplement function CopyMetaFilePict32to16\n");
990 FIXME("\tin the appropriate file.\n");
991 #ifdef SOMEONE_IMPLEMENTED_ME
992 CopyMetaFilePict32to16( GlobalLock16(lpRender->hData16),
993 GlobalLock(lpRender->hData32) );
994 #endif
995 }
996 else
997 {
998 memcpy( GlobalLock16(lpRender->hData16),
999 GlobalLock(lpRender->hData32),
1000 size );
1001 }
Noel Borthwick29700671999-09-03 15:17:57 +00001002 GlobalUnlock16(lpRender->hData16);
1003 GlobalUnlock(lpRender->hData32);
Pascal Cuoq724f1901998-10-26 10:58:16 +00001004 }
1005 }
1006
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001007 TRACE("\treturning %04x (type %i)\n",
Noel Borthwick29700671999-09-03 15:17:57 +00001008 lpRender->hData16, lpRender->wFormatID);
1009 return lpRender->hData16;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001010}
1011
1012
1013/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001014 * GetClipboardData (USER32.@)
Alexandre Julliard21979011997-03-05 08:22:35 +00001015 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001016HANDLE WINAPI GetClipboardData( UINT wFormat )
Alexandre Julliard21979011997-03-05 08:22:35 +00001017{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001018 LPWINE_CLIPFORMAT lpRender = ClipFormats;
Pascal Cuoq724f1901998-10-26 10:58:16 +00001019
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001020 TRACE("(%08X)\n", wFormat);
Pascal Cuoq724f1901998-10-26 10:58:16 +00001021
Noel Borthwick29700671999-09-03 15:17:57 +00001022 if (CLIPBOARD_IsLocked())
Pascal Cuoq724f1901998-10-26 10:58:16 +00001023 {
Francois Gougete76218d2001-05-09 17:31:31 +00001024 WARN("Clipboard not opened by calling task!\n");
Noel Borthwick29700671999-09-03 15:17:57 +00001025 return 0;
Pascal Cuoq724f1901998-10-26 10:58:16 +00001026 }
Noel Borthwick29700671999-09-03 15:17:57 +00001027
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +00001028 if( wFormat == CF_UNICODETEXT || wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
Pascal Cuoq724f1901998-10-26 10:58:16 +00001029 {
Noel Borthwick29700671999-09-03 15:17:57 +00001030 lpRender = CLIPBOARD_RenderText(wFormat);
1031 if ( !lpRender ) return 0;
Pascal Cuoq724f1901998-10-26 10:58:16 +00001032 }
1033 else
1034 {
1035 lpRender = __lookup_format( ClipFormats, wFormat );
Noel Borthwick29700671999-09-03 15:17:57 +00001036 if( !lpRender || !CLIPBOARD_RenderFormat(lpRender) ) return 0;
Pascal Cuoq724f1901998-10-26 10:58:16 +00001037 }
1038
Noel Borthwick29700671999-09-03 15:17:57 +00001039 /* Convert between 16 -> 32 bit data, if necessary */
Francis Beaudet56ab55d1999-10-24 20:22:24 +00001040 if( lpRender->hData16 && !lpRender->hData32
1041 && CLIPBOARD_IsMemoryObject(wFormat) )
Pascal Cuoq724f1901998-10-26 10:58:16 +00001042 {
1043 int size;
Noel Borthwick29700671999-09-03 15:17:57 +00001044 if( lpRender->wFormatID == CF_METAFILEPICT )
Alexandre Julliarda3960291999-02-26 11:11:13 +00001045 size = sizeof( METAFILEPICT );
Pascal Cuoq724f1901998-10-26 10:58:16 +00001046 else
Noel Borthwick29700671999-09-03 15:17:57 +00001047 size = GlobalSize16(lpRender->hData16);
1048 lpRender->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE,
Noel Borthwick83579c81999-07-24 12:18:04 +00001049 size);
Noel Borthwick29700671999-09-03 15:17:57 +00001050 if( lpRender->wFormatID == CF_METAFILEPICT )
Pascal Cuoq724f1901998-10-26 10:58:16 +00001051 {
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001052 FIXME("\timplement function CopyMetaFilePict16to32\n");
1053 FIXME("\tin the appropriate file.\n");
Pascal Cuoq724f1901998-10-26 10:58:16 +00001054#ifdef SOMEONE_IMPLEMENTED_ME
Noel Borthwick29700671999-09-03 15:17:57 +00001055 CopyMetaFilePict16to32( GlobalLock16(lpRender->hData32),
1056 GlobalLock(lpRender->hData16) );
Pascal Cuoq724f1901998-10-26 10:58:16 +00001057#endif
1058 }
1059 else
1060 {
Noel Borthwick29700671999-09-03 15:17:57 +00001061 memcpy( GlobalLock(lpRender->hData32),
1062 GlobalLock16(lpRender->hData16),
Pascal Cuoq724f1901998-10-26 10:58:16 +00001063 size );
1064 }
Noel Borthwick29700671999-09-03 15:17:57 +00001065 GlobalUnlock(lpRender->hData32);
1066 GlobalUnlock16(lpRender->hData16);
Pascal Cuoq724f1901998-10-26 10:58:16 +00001067 }
1068
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001069 TRACE("\treturning %04x (type %i)\n",
Noel Borthwick29700671999-09-03 15:17:57 +00001070 lpRender->hData32, lpRender->wFormatID);
1071 return lpRender->hData32;
Alexandre Julliard21979011997-03-05 08:22:35 +00001072}
1073
Noel Borthwick29700671999-09-03 15:17:57 +00001074
Alexandre Julliard21979011997-03-05 08:22:35 +00001075/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001076 * CountClipboardFormats (USER.143)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001077 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001078INT16 WINAPI CountClipboardFormats16(void)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001079{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001080 return CountClipboardFormats();
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001081}
1082
1083
1084/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001085 * CountClipboardFormats (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001086 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001087INT WINAPI CountClipboardFormats(void)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001088{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001089 INT FormatCount = 0;
1090 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001091
Noel Borthwick29700671999-09-03 15:17:57 +00001092 TRACE("()\n");
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001093
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001094 while(TRUE)
1095 {
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001096 if (lpFormat == NULL) break;
Alex Korobka44a1b591999-04-01 12:03:52 +00001097
Noel Borthwick29700671999-09-03 15:17:57 +00001098 if( lpFormat->wFormatID != CF_TEXT ) /* Don't count CF_TEXT */
1099 {
1100 /*
1101 * The format is available if either:
1102 * 1. The data is already in the cache.
1103 * 2. The selection is not owned by us(WINE) and the data is
1104 * available to the clipboard driver.
1105 */
1106 if ( lpFormat->wDataPresent ||
Alexandre Julliard42d20f92000-08-10 01:16:19 +00001107 ( !USER_Driver.pIsSelectionOwner()
1108 && USER_Driver.pIsClipboardFormatAvailable( lpFormat->wFormatID ) ) )
Noel Borthwick29700671999-09-03 15:17:57 +00001109 {
Juergen Schmied1c35dae2000-02-07 16:22:57 +00001110 TRACE("\tdata found for format 0x%04x(%s)\n",
Noel Borthwick29700671999-09-03 15:17:57 +00001111 lpFormat->wFormatID, CLIPBOARD_GetFormatName(lpFormat->wFormatID));
1112 FormatCount++;
1113 }
1114 }
1115
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001116 lpFormat = lpFormat->NextFormat;
1117 }
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001118
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +00001119 /* these are equivalent, adjust the total */
1120 FormatCount += (ClipFormats[CF_UNICODETEXT-1].wDataPresent ||
1121 ClipFormats[CF_TEXT-1].wDataPresent ||
1122 ClipFormats[CF_OEMTEXT-1].wDataPresent) ? 1 : 0;
Alex Korobka44a1b591999-04-01 12:03:52 +00001123
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001124 TRACE("\ttotal %d\n", FormatCount);
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001125 return FormatCount;
1126}
1127
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001128/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001129 * EnumClipboardFormats (USER.144)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001130 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001131UINT16 WINAPI EnumClipboardFormats16( UINT16 wFormat )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001132{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001133 return EnumClipboardFormats( wFormat );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001134}
1135
1136
1137/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001138 * EnumClipboardFormats (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001139 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001140UINT WINAPI EnumClipboardFormats( UINT wFormat )
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001141{
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001142 TRACE("(%04X)\n", wFormat);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001143
Noel Borthwick29700671999-09-03 15:17:57 +00001144 if (CLIPBOARD_IsLocked())
1145 {
Francois Gougete76218d2001-05-09 17:31:31 +00001146 WARN("Clipboard not opened by calling task!\n");
Noel Borthwick29700671999-09-03 15:17:57 +00001147 return 0;
1148 }
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001149
Gerard Patel9289a5d2000-12-22 23:26:18 +00001150 return CLIPBOARD_EnumClipboardFormats(wFormat);
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001151}
1152
1153
1154/**************************************************************************
Dmitry Timoshkov56a19922001-07-02 01:21:26 +00001155 * RegisterClipboardFormatA (USER32.@)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001156 */
Dmitry Timoshkov56a19922001-07-02 01:21:26 +00001157UINT WINAPI RegisterClipboardFormatA( LPCSTR FormatName )
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001158{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001159 LPWINE_CLIPFORMAT lpNewFormat;
1160 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001161
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001162 if (FormatName == NULL) return 0;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001163
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001164 TRACE("('%s') !\n", FormatName);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001165
1166 /* walk format chain to see if it's already registered */
1167
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001168 while(TRUE)
1169 {
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001170 if ( !strcmp(lpFormat->Name,FormatName) )
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001171 {
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001172 lpFormat->wRefCount++;
1173 return lpFormat->wFormatID;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001174 }
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001175
1176 if ( lpFormat->NextFormat == NULL ) break;
1177
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001178 lpFormat = lpFormat->NextFormat;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001179 }
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001180
1181 /* allocate storage for new format entry */
1182
Dimitrie O. Paun9ad96362000-03-19 14:29:50 +00001183 lpNewFormat = (LPWINE_CLIPFORMAT)HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_CLIPFORMAT));
1184 if(lpNewFormat == NULL) {
Francois Gougete76218d2001-05-09 17:31:31 +00001185 WARN("No more memory for a new format!\n");
Dimitrie O. Paun9ad96362000-03-19 14:29:50 +00001186 return 0;
1187 }
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001188 lpFormat->NextFormat = lpNewFormat;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001189 lpNewFormat->wFormatID = LastRegFormat;
1190 lpNewFormat->wRefCount = 1;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001191
Alexandre Julliard5f728ca2001-07-24 21:45:22 +00001192 if (!(lpNewFormat->Name = HeapAlloc(GetProcessHeap(), 0, strlen(FormatName)+1 )))
1193 {
Francois Gougete76218d2001-05-09 17:31:31 +00001194 WARN("No more memory for the new format name!\n");
Dimitrie O. Paun9ad96362000-03-19 14:29:50 +00001195 HeapFree(GetProcessHeap(), 0, lpNewFormat);
1196 return 0;
1197 }
Alexandre Julliard5f728ca2001-07-24 21:45:22 +00001198 strcpy( lpNewFormat->Name, FormatName );
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001199
1200 lpNewFormat->wDataPresent = 0;
Pascal Cuoq724f1901998-10-26 10:58:16 +00001201 lpNewFormat->hData16 = 0;
Noel Borthwick83579c81999-07-24 12:18:04 +00001202 lpNewFormat->hDataSrc32 = 0;
Pascal Cuoq724f1901998-10-26 10:58:16 +00001203 lpNewFormat->hData32 = 0;
Noel Borthwick29700671999-09-03 15:17:57 +00001204 lpNewFormat->drvData = 0;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001205 lpNewFormat->PrevFormat = lpFormat;
1206 lpNewFormat->NextFormat = NULL;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001207
Noel Borthwick29700671999-09-03 15:17:57 +00001208 /* Pass on the registration request to the driver */
Alexandre Julliard42d20f92000-08-10 01:16:19 +00001209 USER_Driver.pRegisterClipboardFormat( FormatName );
Noel Borthwick29700671999-09-03 15:17:57 +00001210
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001211 return LastRegFormat++;
1212}
1213
1214
1215/**************************************************************************
Dmitry Timoshkov56a19922001-07-02 01:21:26 +00001216 * RegisterClipboardFormat (USER.145)
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001217 */
Dmitry Timoshkov56a19922001-07-02 01:21:26 +00001218UINT16 WINAPI RegisterClipboardFormat16( LPCSTR FormatName )
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001219{
Dmitry Timoshkov56a19922001-07-02 01:21:26 +00001220 return RegisterClipboardFormatA( FormatName );
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001221}
1222
1223
1224/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001225 * RegisterClipboardFormatW (USER32.@)
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001226 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001227UINT WINAPI RegisterClipboardFormatW( LPCWSTR formatName )
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001228{
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001229 LPSTR aFormat = HEAP_strdupWtoA( GetProcessHeap(), 0, formatName );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001230 UINT ret = RegisterClipboardFormatA( aFormat );
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001231 HeapFree( GetProcessHeap(), 0, aFormat );
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001232 return ret;
1233}
1234
Noel Borthwick29700671999-09-03 15:17:57 +00001235
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001236/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001237 * GetClipboardFormatName (USER.146)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001238 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001239INT16 WINAPI GetClipboardFormatName16( UINT16 wFormat, LPSTR retStr, INT16 maxlen )
Alexandre Julliard21979011997-03-05 08:22:35 +00001240{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001241 return GetClipboardFormatNameA( wFormat, retStr, maxlen );
Alexandre Julliard21979011997-03-05 08:22:35 +00001242}
1243
1244
1245/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001246 * GetClipboardFormatNameA (USER32.@)
Alexandre Julliard21979011997-03-05 08:22:35 +00001247 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001248INT WINAPI GetClipboardFormatNameA( UINT wFormat, LPSTR retStr, INT maxlen )
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001249{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001250 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001251
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001252 TRACE("(%04X, %p, %d) !\n", wFormat, retStr, maxlen);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001253
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001254 if (lpFormat == NULL || lpFormat->Name == NULL ||
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001255 lpFormat->wFormatID < CF_REGFORMATBASE) return 0;
1256
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001257 TRACE("Name='%s' !\n", lpFormat->Name);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001258
Alexandre Julliarda3960291999-02-26 11:11:13 +00001259 lstrcpynA( retStr, lpFormat->Name, maxlen );
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001260 return strlen(retStr);
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001261}
1262
1263
1264/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001265 * GetClipboardFormatNameW (USER32.@)
Alexandre Julliard21979011997-03-05 08:22:35 +00001266 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001267INT WINAPI GetClipboardFormatNameW( UINT wFormat, LPWSTR retStr, INT maxlen )
Alexandre Julliard21979011997-03-05 08:22:35 +00001268{
Dimitrie O. Paun4d48dd32000-04-30 12:22:18 +00001269 INT ret;
1270 LPSTR p = HeapAlloc( GetProcessHeap(), 0, maxlen );
1271 if(p == NULL) return 0; /* FIXME: is this the correct failure value? */
1272
1273 ret = GetClipboardFormatNameA( wFormat, p, maxlen );
Alexandre Julliard24a62ab2000-11-28 22:40:56 +00001274
1275 if (maxlen > 0 && !MultiByteToWideChar( CP_ACP, 0, p, -1, retStr, maxlen ))
1276 retStr[maxlen-1] = 0;
Alexandre Julliard21979011997-03-05 08:22:35 +00001277 HeapFree( GetProcessHeap(), 0, p );
1278 return ret;
1279}
1280
1281
1282/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001283 * SetClipboardViewer (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001284 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001285HWND WINAPI SetClipboardViewer( HWND hWnd )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001286{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001287 HWND hwndPrev = hWndViewer;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001288
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001289 TRACE("(%04x): returning %04x\n", hWnd, hwndPrev);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001290
Alexandre Julliard37a46392001-09-12 17:19:13 +00001291 hWndViewer = WIN_GetFullHandle( hWnd );
Alexandre Julliardecc37121994-11-22 16:31:29 +00001292 return hwndPrev;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001293}
1294
1295
1296/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001297 * GetClipboardViewer (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001298 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001299HWND WINAPI GetClipboardViewer(void)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001300{
Noel Borthwick29700671999-09-03 15:17:57 +00001301 TRACE("()\n");
Alexandre Julliardaca05781994-10-17 18:12:41 +00001302 return hWndViewer;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001303}
1304
1305
1306/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001307 * ChangeClipboardChain (USER32.@)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001308 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001309BOOL WINAPI ChangeClipboardChain(HWND hWnd, HWND hWndNext)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001310{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001311 BOOL bRet = 0;
Alexandre Julliard234bc241994-12-10 13:02:28 +00001312
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001313 FIXME("(0x%04x, 0x%04x): stub?\n", hWnd, hWndNext);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001314
1315 if( hWndViewer )
Alexandre Julliardcb25e252001-08-08 23:28:42 +00001316 bRet = !SendMessageW( hWndViewer, WM_CHANGECBCHAIN, (WPARAM)hWnd, (LPARAM)hWndNext );
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001317 else
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001318 WARN("hWndViewer is lost\n");
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001319
Alexandre Julliardf44bbb82001-09-14 00:24:39 +00001320 if( WIN_GetFullHandle(hWnd) == hWndViewer ) hWndViewer = WIN_GetFullHandle( hWndNext );
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001321
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001322 return bRet;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001323}
1324
1325
1326/**************************************************************************
Patrik Stridvall0c610282001-01-25 22:22:21 +00001327 * IsClipboardFormatAvailable (USER.193)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001328 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001329BOOL16 WINAPI IsClipboardFormatAvailable16( UINT16 wFormat )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001330{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001331 return IsClipboardFormatAvailable( wFormat );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001332}
1333
1334
1335/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001336 * IsClipboardFormatAvailable (USER32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001337 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001338BOOL WINAPI IsClipboardFormatAvailable( UINT wFormat )
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001339{
Noel Borthwick29700671999-09-03 15:17:57 +00001340 BOOL bRet;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001341
Noel Borthwick29700671999-09-03 15:17:57 +00001342 if (wFormat == 0) /* Reject this case quickly */
1343 bRet = FALSE;
Dmitry Timoshkov1df0d362000-12-11 01:09:56 +00001344 else
Gerard Patel9289a5d2000-12-22 23:26:18 +00001345 {
1346 UINT iret = CLIPBOARD_EnumClipboardFormats(wFormat - 1);
1347 if ((wFormat == CF_TEXT) || (wFormat == CF_OEMTEXT) || (wFormat == CF_UNICODETEXT))
1348 bRet = ((iret == CF_TEXT) || (iret == CF_OEMTEXT) || (iret == CF_UNICODETEXT));
1349 else
1350 bRet = iret == wFormat;
1351 }
Noel Borthwick29700671999-09-03 15:17:57 +00001352 TRACE("(%04X)- ret(%d)\n", wFormat, bRet);
1353 return bRet;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001354}
1355
1356
1357/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001358 * GetOpenClipboardWindow (USER32.@)
Noel Borthwick29700671999-09-03 15:17:57 +00001359 * FIXME: This wont work if an external app owns the selection
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001360 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001361HWND WINAPI GetOpenClipboardWindow(void)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001362{
Noel Borthwick29700671999-09-03 15:17:57 +00001363 TRACE("()\n");
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001364 return hWndClipWindow;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001365}
1366
1367
1368/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001369 * GetPriorityClipboardFormat (USER32.@)
Alexandre Julliard21979011997-03-05 08:22:35 +00001370 */
Alexandre Julliardd23a82b2001-09-19 20:37:04 +00001371INT WINAPI GetPriorityClipboardFormat( UINT *list, INT nCount )
Alexandre Julliard21979011997-03-05 08:22:35 +00001372{
Alexandre Julliardd23a82b2001-09-19 20:37:04 +00001373 int i;
Noel Borthwick29700671999-09-03 15:17:57 +00001374 TRACE("()\n");
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001375
Alexandre Julliardd23a82b2001-09-19 20:37:04 +00001376 if(CountClipboardFormats() == 0) return 0;
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001377
Alexandre Julliardd23a82b2001-09-19 20:37:04 +00001378 for (i = 0; i < nCount; i++)
1379 if (IsClipboardFormatAvailable( list[i] )) return list[i];
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001380 return -1;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001381}
1382
David Elliott44f84b52000-10-29 01:24:54 +00001383
1384/**************************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +00001385 * GetClipboardSequenceNumber (USER32.@)
David Elliott44f84b52000-10-29 01:24:54 +00001386 * Supported on Win2k/Win98
1387 * MSDN: Windows clipboard code keeps a serial number for the clipboard
1388 * for each window station. The number is incremented whenever the
1389 * contents change or are emptied.
1390 * If you do not have WINSTA_ACCESSCLIPBOARD then the function returns 0
1391 */
1392DWORD WINAPI GetClipboardSequenceNumber(VOID)
1393{
1394 FIXME("Returning 0, see windows/clipboard.c\n");
1395 /* FIXME: Use serial numbers */
1396 return 0;
1397}