blob: bb44967448015bb2e5ae234a9cceda26dc282bbe [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)
15 *
16 * TODO:
Alexandre Julliard1e9ac791996-06-06 18:38:27 +000017 *
18 */
Alexandre Julliardfb9a9191994-03-01 19:48:04 +000019
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000020#include <stdlib.h>
Alexandre Julliardfb9a9191994-03-01 19:48:04 +000021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Alexandre Julliard1e9ac791996-06-06 18:38:27 +000025#include <string.h>
Jeremy Whited3e22d92000-02-10 19:03:02 +000026#include "windef.h"
27#include "wingdi.h"
Marcus Meissner61afa331999-02-22 10:16:00 +000028#include "winuser.h"
Marcus Meissner219cfd81999-02-24 13:05:13 +000029#include "wine/winuser16.h"
Noel Borthwick29700671999-09-03 15:17:57 +000030#include "wine/winbase16.h"
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +000031#include "heap.h"
Marcus Meissner61afa331999-02-22 10:16:00 +000032#include "message.h"
Noel Borthwick29700671999-09-03 15:17:57 +000033#include "task.h"
34#include "queue.h"
Alexandre Julliard42d20f92000-08-10 01:16:19 +000035#include "user.h"
Alexandre Julliard234bc241994-12-10 13:02:28 +000036#include "clipboard.h"
Alexandre Julliard359f497e1999-07-04 16:02:24 +000037#include "debugtools.h"
Alexandre Julliardfb9a9191994-03-01 19:48:04 +000038
Alexandre Julliard42d20f92000-08-10 01:16:19 +000039DEFAULT_DEBUG_CHANNEL(clipboard);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000040
Alexandre Julliard1e9ac791996-06-06 18:38:27 +000041#define CF_REGFORMATBASE 0xC000
42
Patrik Stridvalle35d6361998-12-07 09:13:40 +000043/**************************************************************************
Noel Borthwick29700671999-09-03 15:17:57 +000044 * Clipboard context global variables
Alexandre Julliard1e9ac791996-06-06 18:38:27 +000045 */
46
Noel Borthwick29700671999-09-03 15:17:57 +000047static HANDLE hClipLock = 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +000048static BOOL bCBHasChanged = FALSE;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +000049
Noel Borthwick29700671999-09-03 15:17:57 +000050HWND hWndClipWindow = 0; /* window that last opened clipboard */
51HWND hWndClipOwner = 0; /* current clipboard owner */
52HANDLE16 hTaskClipOwner = 0; /* clipboard owner's task */
Alexandre Julliarda3960291999-02-26 11:11:13 +000053static HWND hWndViewer = 0; /* start of viewers chain */
Alexandre Julliard1e9ac791996-06-06 18:38:27 +000054
Alexandre Julliard1e9ac791996-06-06 18:38:27 +000055static WORD LastRegFormat = CF_REGFORMATBASE;
56
Noel Borthwick29700671999-09-03 15:17:57 +000057/* Clipboard cache initial data.
58 * WARNING: This data ordering is dependendent on the WINE_CLIPFORMAT structure
59 * declared in clipboard.h
60 */
Juergen Schmied1c35dae2000-02-07 16:22:57 +000061WINE_CLIPFORMAT ClipFormats[17] = {
Alexandre Julliard42d20f92000-08-10 01:16:19 +000062 { CF_TEXT, 1, 0, "Text", 0, 0, 0, 0, NULL, &ClipFormats[1]},
63 { CF_BITMAP, 1, 0, "Bitmap", 0, 0, 0, 0, &ClipFormats[0], &ClipFormats[2]},
64 { CF_METAFILEPICT, 1, 0, "MetaFile Picture", 0, 0, 0, 0, &ClipFormats[1], &ClipFormats[3]},
65 { CF_SYLK, 1, 0, "Sylk", 0, 0, 0, 0, &ClipFormats[2], &ClipFormats[4]},
66 { CF_DIF, 1, 0, "DIF", 0, 0, 0, 0, &ClipFormats[3], &ClipFormats[5]},
67 { CF_TIFF, 1, 0, "TIFF", 0, 0, 0, 0, &ClipFormats[4], &ClipFormats[6]},
68 { CF_OEMTEXT, 1, 0, "OEM Text", 0, 0, 0, 0, &ClipFormats[5], &ClipFormats[7]},
69 { CF_DIB, 1, 0, "DIB", 0, 0, 0, 0, &ClipFormats[6], &ClipFormats[8]},
70 { CF_PALETTE, 1, 0, "Palette", 0, 0, 0, 0, &ClipFormats[7], &ClipFormats[9]},
71 { CF_PENDATA, 1, 0, "PenData", 0, 0, 0, 0, &ClipFormats[8], &ClipFormats[10]},
72 { CF_RIFF, 1, 0, "RIFF", 0, 0, 0, 0, &ClipFormats[9], &ClipFormats[11]},
73 { CF_WAVE, 1, 0, "Wave", 0, 0, 0, 0, &ClipFormats[10], &ClipFormats[12]},
74 { CF_OWNERDISPLAY, 1, 0, "Owner Display", 0, 0, 0, 0, &ClipFormats[11], &ClipFormats[13]},
75 { CF_DSPTEXT, 1, 0, "DSPText", 0, 0, 0, 0, &ClipFormats[12], &ClipFormats[14]},
76 { CF_DSPMETAFILEPICT, 1, 0, "DSPMetaFile Picture", 0, 0, 0, 0, &ClipFormats[13], &ClipFormats[15]},
77 { CF_DSPBITMAP, 1, 0, "DSPBitmap", 0, 0, 0, 0, &ClipFormats[14], &ClipFormats[16]},
78 { CF_HDROP, 1, 0, "HDROP", 0, 0, 0, 0, &ClipFormats[15], NULL}
79};
Alexandre Julliardfb9a9191994-03-01 19:48:04 +000080
Noel Borthwick29700671999-09-03 15:17:57 +000081
82/**************************************************************************
83 * Internal Clipboard implementation methods
84 **************************************************************************/
85
86
87/**************************************************************************
88 * CLIPBOARD_LookupFormat
89 */
Alexandre Julliarda3960291999-02-26 11:11:13 +000090static LPWINE_CLIPFORMAT __lookup_format( LPWINE_CLIPFORMAT lpFormat, WORD wID )
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +000091{
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +000092 while(TRUE)
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +000093 {
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +000094 if (lpFormat == NULL ||
95 lpFormat->wFormatID == wID) break;
96 lpFormat = lpFormat->NextFormat;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +000097 }
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +000098 return lpFormat;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +000099}
100
Noel Borthwick29700671999-09-03 15:17:57 +0000101LPWINE_CLIPFORMAT CLIPBOARD_LookupFormat( WORD wID )
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000102{
Noel Borthwick29700671999-09-03 15:17:57 +0000103 return __lookup_format( ClipFormats, wID );
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000104}
105
Noel Borthwick29700671999-09-03 15:17:57 +0000106/**************************************************************************
107 * CLIPBOARD_IsLocked
108 * Check if the clipboard cache is available to the caller
109 */
110BOOL CLIPBOARD_IsLocked()
111{
112 BOOL bIsLocked = TRUE;
113 HANDLE16 hTaskCur = GetCurrentTask();
114
115 /*
116 * The clipboard is available:
117 * 1. if the caller's task has opened the clipboard,
118 * or
119 * 2. if the caller is the clipboard owners task, AND is responding to a
120 * WM_RENDERFORMAT message.
121 */
122 if ( hClipLock == hTaskCur )
123 bIsLocked = FALSE;
124
125 else if ( hTaskCur == hTaskClipOwner )
126 {
127 /* Check if we're currently executing inside a window procedure
128 * called in response to a WM_RENDERFORMAT message. A WM_RENDERFORMAT
129 * handler is not permitted to open the clipboard since it has been opened
130 * by another client. However the handler must have access to the
131 * clipboard in order to update data in response to this message.
132 */
133 MESSAGEQUEUE *queue = QUEUE_Lock( GetFastQueue16() );
134
135 if ( queue
136 && queue->smWaiting
137 && queue->smWaiting->msg == WM_RENDERFORMAT
138 && queue->smWaiting->hSrcQueue
139 )
140 bIsLocked = FALSE;
141
142 QUEUE_Unlock( queue );
143 }
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
279 if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000280 return ClipFormats[CF_TEXT-1].wDataPresent ||
281 ClipFormats[CF_OEMTEXT-1].wDataPresent;
282 else
283 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000284 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000285 if( lpFormat ) return (lpFormat->wDataPresent);
286 }
287 return FALSE;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000288}
289
290/**************************************************************************
Noel Borthwick29700671999-09-03 15:17:57 +0000291 * CLIPBOARD_IsCacheRendered
292 * Checks if any data needs to be rendered to the clipboard cache
293 * RETURNS:
294 * TRUE - All clipboard data is available in the cache
295 * FALSE - Some data is marked for delayed render and needs rendering
296 */
297BOOL CLIPBOARD_IsCacheRendered()
298{
299 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
300
301 /* check if all formats were rendered */
302 while(lpFormat)
303 {
304 if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
305 return FALSE;
306
307 lpFormat = lpFormat->NextFormat;
308 }
309
310 return TRUE;
311}
312
313
314/**************************************************************************
Noel Borthwick83579c81999-07-24 12:18:04 +0000315 * CLIPBOARD_IsMemoryObject
316 * Tests if the clipboard format specifies a memory object
317 */
318BOOL CLIPBOARD_IsMemoryObject( WORD wFormat )
319{
320 switch(wFormat)
321 {
322 case CF_BITMAP:
323 case CF_METAFILEPICT:
324 case CF_DSPTEXT:
325 case CF_ENHMETAFILE:
326 case CF_HDROP:
327 case CF_PALETTE:
328 case CF_PENDATA:
329 return FALSE;
330 default:
331 return TRUE;
332 }
333}
334
335/***********************************************************************
336 * CLIPBOARD_GlobalDupMem( HGLOBAL )
337 * Helper method to duplicate an HGLOBAL chunk of memory into shared memory
338 */
339HGLOBAL CLIPBOARD_GlobalDupMem( HGLOBAL hGlobalSrc )
340{
341 HGLOBAL hGlobalDest;
342 PVOID pGlobalSrc, pGlobalDest;
343 DWORD cBytes;
344
345 if ( !hGlobalSrc )
346 return 0;
347
348 cBytes = GlobalSize(hGlobalSrc);
349 if ( 0 == cBytes )
350 return 0;
351
352 /* Turn on the DDESHARE and _MOVEABLE flags explicitly */
353 hGlobalDest = GlobalAlloc( GlobalFlags(hGlobalSrc) | GMEM_DDESHARE | GMEM_MOVEABLE,
354 cBytes );
355 if ( !hGlobalDest )
356 return 0;
357
358 pGlobalSrc = GlobalLock(hGlobalSrc);
359 pGlobalDest = GlobalLock(hGlobalDest);
360 if ( !pGlobalSrc || !pGlobalDest )
361 return 0;
362
363 memcpy(pGlobalDest, pGlobalSrc, cBytes);
364
365 GlobalUnlock(hGlobalSrc);
366 GlobalUnlock(hGlobalDest);
367
368 return hGlobalDest;
369}
370
371/**************************************************************************
Noel Borthwick29700671999-09-03 15:17:57 +0000372 * CLIPBOARD_GetFormatName
373 * Gets the format name associated with an ID
374 */
375char * CLIPBOARD_GetFormatName(UINT wFormat)
376{
377 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
378 return (lpFormat) ? lpFormat->Name : NULL;
379}
380
381
382/**************************************************************************
383 * CLIPBOARD_RenderFormat
384 */
385static BOOL CLIPBOARD_RenderFormat(LPWINE_CLIPFORMAT lpFormat)
386{
387 /*
388 * If WINE is not the selection owner, and the format is available
389 * we must ask the the driver to render the data to the clipboard cache.
390 */
Alexandre Julliard42d20f92000-08-10 01:16:19 +0000391 if ( !USER_Driver.pIsSelectionOwner()
392 && USER_Driver.pIsClipboardFormatAvailable( lpFormat->wFormatID ) )
Noel Borthwick29700671999-09-03 15:17:57 +0000393 {
Alexandre Julliard42d20f92000-08-10 01:16:19 +0000394 if ( !USER_Driver.pGetClipboardData( lpFormat->wFormatID ) )
Noel Borthwick29700671999-09-03 15:17:57 +0000395 return FALSE;
396 }
397 /*
398 * If Wine owns the clipboard, and the data is marked for delayed render,
399 * render it now.
400 */
401 else if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
402 {
403 if( IsWindow(hWndClipOwner) )
404 {
405 /* Send a WM_RENDERFORMAT message to notify the owner to render the
406 * data requested into the clipboard.
407 */
408 TRACE("Sending WM_RENDERFORMAT message\n");
409 SendMessage16(hWndClipOwner,WM_RENDERFORMAT,
410 (WPARAM16)lpFormat->wFormatID,0L);
411 }
412 else
413 {
414 WARN("\thWndClipOwner (%04x) is lost!\n",
415 hWndClipOwner);
416 CLIPBOARD_ReleaseOwner();
417 lpFormat->wDataPresent = 0;
418 return FALSE;
419 }
420 }
421
422 return (lpFormat->hData16 || lpFormat->hData32) ? TRUE : FALSE;
423}
424
425
426/**************************************************************************
427 * CLIPBOARD_RenderText
428 *
429 * Renders text to the clipboard buffer converting between UNIX and DOS formats.
430 *
431 * RETURNS: pointer to the WINE_CLIPFORMAT if successful, NULL otherwise
432 *
433 * FIXME: Should be a pair of driver functions that convert between OEM text and Windows.
434 *
435 */
436static LPWINE_CLIPFORMAT CLIPBOARD_RenderText( UINT wFormat )
437{
438 LPWINE_CLIPFORMAT lpSource = ClipFormats;
439 LPWINE_CLIPFORMAT lpTarget;
440
441 /* Asked for CF_TEXT and not available - always attempt to convert from CF_OEM_TEXT */
442 if( wFormat == CF_TEXT && !ClipFormats[CF_TEXT-1].wDataPresent )
443 {
444 /* Convert OEMTEXT -> TEXT */
445 lpSource = &ClipFormats[CF_OEMTEXT-1];
446 lpTarget = &ClipFormats[CF_TEXT-1];
447
448 TRACE("\tOEMTEXT -> TEXT\n");
449 }
450 /* Asked for CF_OEM_TEXT, and CF_TEXT available */
451 else if( wFormat == CF_OEMTEXT && !ClipFormats[CF_OEMTEXT-1].wDataPresent
452 && ClipFormats[CF_TEXT-1].wDataPresent )
453 {
454 /* Convert TEXT -> OEMTEXT */
455 lpSource = &ClipFormats[CF_TEXT-1];
456 lpTarget = &ClipFormats[CF_OEMTEXT-1];
457
458 TRACE("\tTEXT -> OEMTEXT\n");
459 }
460 /* Text format requested is available - no conversion necessary */
461 else
462 {
463 lpSource = __lookup_format( ClipFormats, wFormat );
464 lpTarget = lpSource;
465 }
466
467 /* First render the source text format */
468 if ( !lpSource || !CLIPBOARD_RenderFormat(lpSource) ) return NULL;
469
470 /* Convert to the desired target text format, if necessary */
471 if( lpTarget != lpSource && !lpTarget->hData16 && !lpTarget->hData32 )
472 {
473 UINT16 size;
474 LPCSTR lpstrS;
475 LPSTR lpstrT;
476
477 if (lpSource->hData32)
478 {
479 size = GlobalSize( lpSource->hData32 );
480 lpstrS = (LPSTR)GlobalLock(lpSource->hData32);
481 }
482 else
483 {
484 size = GlobalSize16( lpSource->hData16 );
485 lpstrS = (LPSTR)GlobalLock16(lpSource->hData16);
486 }
487
488 if( !lpstrS ) return NULL;
489 TRACE("\tconverting from '%s' to '%s', %i chars\n",
490 lpSource->Name, lpTarget->Name, size);
491
Francis Beaudet56ab55d1999-10-24 20:22:24 +0000492 lpTarget->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, size);
Noel Borthwick29700671999-09-03 15:17:57 +0000493 lpstrT = (LPSTR)GlobalLock(lpTarget->hData32);
494
495 if( lpstrT )
496 {
497 if( lpSource->wFormatID == CF_TEXT )
498 CharToOemBuffA(lpstrS, lpstrT, size);
499 else
500 OemToCharBuffA(lpstrS, lpstrT, size);
501 TRACE("\tgot %s\n", lpstrT);
502 GlobalUnlock(lpTarget->hData32);
503 }
504 else
505 lpTarget->hData32 = 0;
506
507 /* Unlock source */
508 if (lpSource->hData32)
509 GlobalUnlock(lpSource->hData32);
510 else
511 GlobalUnlock16(lpSource->hData16);
512 }
513
514 return (lpTarget->hData16 || lpTarget->hData32) ? lpTarget : NULL;
515}
516
517/**************************************************************************
518 * WIN32 Clipboard implementation
519 **************************************************************************/
520
521/**************************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000522 * OpenClipboard16 (USER.137)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000523 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000524BOOL16 WINAPI OpenClipboard16( HWND16 hWnd )
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000525{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000526 return OpenClipboard( hWnd );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000527}
528
529
530/**************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000531 * OpenClipboard (USER32.407)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000532 *
533 * Note: Netscape uses NULL hWnd to open the clipboard.
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000534 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000535BOOL WINAPI OpenClipboard( HWND hWnd )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000536{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000537 BOOL bRet;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000538
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000539 TRACE("(%04x)...\n", hWnd);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000540
Noel Borthwick29700671999-09-03 15:17:57 +0000541 if (!hClipLock)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000542 {
Noel Borthwick29700671999-09-03 15:17:57 +0000543 hClipLock = GetCurrentTask();
544
545 /* Save current user of the clipboard */
546 hWndClipWindow = hWnd;
547 bCBHasChanged = FALSE;
548 bRet = TRUE;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000549 }
550 else bRet = FALSE;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000551
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000552 TRACE(" returning %i\n", bRet);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000553 return bRet;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000554}
555
556
557/**************************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000558 * CloseClipboard16 (USER.138)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000559 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000560BOOL16 WINAPI CloseClipboard16(void)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000561{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000562 return CloseClipboard();
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000563}
564
565
566/**************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000567 * CloseClipboard (USER32.54)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000568 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000569BOOL WINAPI CloseClipboard(void)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000570{
Noel Borthwick29700671999-09-03 15:17:57 +0000571 TRACE("()\n");
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000572
Noel Borthwick29700671999-09-03 15:17:57 +0000573 if (hClipLock == GetCurrentTask())
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000574 {
575 hWndClipWindow = 0;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000576
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000577 if (bCBHasChanged && hWndViewer)
578 SendMessage16(hWndViewer, WM_DRAWCLIPBOARD, 0, 0L);
Noel Borthwick29700671999-09-03 15:17:57 +0000579 hClipLock = 0;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000580 }
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000581 return TRUE;
582}
583
584
585/**************************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000586 * EmptyClipboard16 (USER.139)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000587 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000588BOOL16 WINAPI EmptyClipboard16(void)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000589{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000590 return EmptyClipboard();
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000591}
592
593
594/**************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000595 * EmptyClipboard (USER32.169)
Noel Borthwick29700671999-09-03 15:17:57 +0000596 * Empties and acquires ownership of the clipboard
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000597 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000598BOOL WINAPI EmptyClipboard(void)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000599{
Noel Borthwick29700671999-09-03 15:17:57 +0000600 TRACE("()\n");
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000601
Noel Borthwick29700671999-09-03 15:17:57 +0000602 if (hClipLock != GetCurrentTask())
603 {
604 WARN("Clipboard not opened by calling task!");
605 return FALSE;
606 }
607
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000608 /* destroy private objects */
609
610 if (hWndClipOwner)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000611 SendMessage16(hWndClipOwner, WM_DESTROYCLIPBOARD, 0, 0L);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000612
Noel Borthwick29700671999-09-03 15:17:57 +0000613 /* empty the cache */
614 CLIPBOARD_EmptyCache(TRUE);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000615
Noel Borthwick29700671999-09-03 15:17:57 +0000616 /* Assign ownership of the clipboard to the current client */
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000617 hWndClipOwner = hWndClipWindow;
618
Noel Borthwick29700671999-09-03 15:17:57 +0000619 /* Save the current task */
620 hTaskClipOwner = GetCurrentTask();
621
622 /* Tell the driver to acquire the selection */
Alexandre Julliard42d20f92000-08-10 01:16:19 +0000623 USER_Driver.pAcquireClipboard();
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000624
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000625 return TRUE;
626}
627
628
629/**************************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000630 * GetClipboardOwner16 (USER.140)
Noel Borthwick29700671999-09-03 15:17:57 +0000631 * FIXME: Can't return the owner if the clipbard is owned by an external app
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000632 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000633HWND16 WINAPI GetClipboardOwner16(void)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000634{
Noel Borthwick29700671999-09-03 15:17:57 +0000635 TRACE("()\n");
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000636 return hWndClipOwner;
637}
638
639
640/**************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000641 * GetClipboardOwner (USER32.225)
Noel Borthwick29700671999-09-03 15:17:57 +0000642 * FIXME: Can't return the owner if the clipbard is owned by an external app
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000643 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000644HWND WINAPI GetClipboardOwner(void)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000645{
Noel Borthwick29700671999-09-03 15:17:57 +0000646 TRACE("()\n");
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000647 return hWndClipOwner;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000648}
649
650
651/**************************************************************************
Alexandre Julliard21979011997-03-05 08:22:35 +0000652 * SetClipboardData16 (USER.141)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000653 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000654HANDLE16 WINAPI SetClipboardData16( UINT16 wFormat, HANDLE16 hData )
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000655{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000656 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000657
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000658 TRACE("(%04X, %04x) !\n", wFormat, hData);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000659
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000660 /* NOTE: If the hData is zero and current owner doesn't match
661 * the window that opened the clipboard then this application
Noel Borthwick29700671999-09-03 15:17:57 +0000662 * is screwed because WM_RENDERFORMAT will go to the owner.
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000663 * (to become the owner it must call EmptyClipboard() before
664 * adding new data).
665 */
666
Noel Borthwick29700671999-09-03 15:17:57 +0000667 if( CLIPBOARD_IsLocked() || !lpFormat ||
668 (!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) )
669 {
Juergen Schmied1c35dae2000-02-07 16:22:57 +0000670 WARN("Invalid hData or clipboard not opened by calling task!\n");
Noel Borthwick29700671999-09-03 15:17:57 +0000671 return 0;
672 }
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000673
Noel Borthwick29700671999-09-03 15:17:57 +0000674 /* Pass on the request to the driver */
Alexandre Julliard42d20f92000-08-10 01:16:19 +0000675 USER_Driver.pSetClipboardData(wFormat);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000676
Pascal Cuoq724f1901998-10-26 10:58:16 +0000677 if ( lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32 )
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000678 {
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000679 CLIPBOARD_DeleteRecord(lpFormat, TRUE);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000680
681 /* delete existing CF_TEXT/CF_OEMTEXT aliases */
682
Pascal Cuoq724f1901998-10-26 10:58:16 +0000683 if( wFormat == CF_TEXT
684 && ( ClipFormats[CF_OEMTEXT-1].hData16
685 || ClipFormats[CF_OEMTEXT-1].hData32 )
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000686 && !ClipFormats[CF_OEMTEXT-1].wDataPresent )
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000687 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
Pascal Cuoq724f1901998-10-26 10:58:16 +0000688 if( wFormat == CF_OEMTEXT
689 && ( ClipFormats[CF_OEMTEXT-1].hData16
690 || ClipFormats[CF_OEMTEXT-1].hData32 )
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000691 && !ClipFormats[CF_TEXT-1].wDataPresent )
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000692 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000693 }
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000694
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000695 bCBHasChanged = TRUE;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000696 lpFormat->wDataPresent = 1;
Pascal Cuoq724f1901998-10-26 10:58:16 +0000697 lpFormat->hData16 = hData; /* 0 is legal, see WM_RENDERFORMAT */
698 lpFormat->hData32 = 0;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000699
Pascal Cuoq724f1901998-10-26 10:58:16 +0000700 return lpFormat->hData16;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000701}
702
Alexandre Julliard21979011997-03-05 08:22:35 +0000703
704/**************************************************************************
Alex Korobka44a1b591999-04-01 12:03:52 +0000705 * SetClipboardData (USER32.470)
Alexandre Julliard21979011997-03-05 08:22:35 +0000706 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000707HANDLE WINAPI SetClipboardData( UINT wFormat, HANDLE hData )
Alexandre Julliard21979011997-03-05 08:22:35 +0000708{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000709 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
Pascal Cuoq724f1901998-10-26 10:58:16 +0000710
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000711 TRACE("(%08X, %08x) !\n", wFormat, hData);
Pascal Cuoq724f1901998-10-26 10:58:16 +0000712
713 /* NOTE: If the hData is zero and current owner doesn't match
714 * the window that opened the clipboard then this application
Noel Borthwick29700671999-09-03 15:17:57 +0000715 * is screwed because WM_RENDERFORMAT will go to the owner.
Pascal Cuoq724f1901998-10-26 10:58:16 +0000716 * (to become the owner it must call EmptyClipboard() before
717 * adding new data).
718 */
719
Noel Borthwick29700671999-09-03 15:17:57 +0000720 if( CLIPBOARD_IsLocked() || !lpFormat ||
721 (!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) )
722 {
Juergen Schmied1c35dae2000-02-07 16:22:57 +0000723 WARN("Invalid hData or clipboard not opened by calling task!\n");
Noel Borthwick29700671999-09-03 15:17:57 +0000724 return 0;
725 }
Pascal Cuoq724f1901998-10-26 10:58:16 +0000726
Noel Borthwick29700671999-09-03 15:17:57 +0000727 /* Tell the driver to acquire the selection */
Alexandre Julliard42d20f92000-08-10 01:16:19 +0000728 USER_Driver.pAcquireClipboard();
Pascal Cuoq724f1901998-10-26 10:58:16 +0000729
Noel Borthwick29700671999-09-03 15:17:57 +0000730 if ( lpFormat->wDataPresent &&
731 (lpFormat->hData16 || lpFormat->hData32) )
Pascal Cuoq724f1901998-10-26 10:58:16 +0000732 {
733 CLIPBOARD_DeleteRecord(lpFormat, TRUE);
734
735 /* delete existing CF_TEXT/CF_OEMTEXT aliases */
736
737 if( wFormat == CF_TEXT
738 && ( ClipFormats[CF_OEMTEXT-1].hData16
739 || ClipFormats[CF_OEMTEXT-1].hData32 )
740 && !ClipFormats[CF_OEMTEXT-1].wDataPresent )
741 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
742 if( wFormat == CF_OEMTEXT
743 && ( ClipFormats[CF_OEMTEXT-1].hData16
744 || ClipFormats[CF_OEMTEXT-1].hData32 )
745 && !ClipFormats[CF_TEXT-1].wDataPresent )
746 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
747 }
748
749 bCBHasChanged = TRUE;
750 lpFormat->wDataPresent = 1;
Noel Borthwick83579c81999-07-24 12:18:04 +0000751 lpFormat->hDataSrc32 = hData; /* Save the source handle */
752
753 /*
754 * Make a shared duplicate if the memory is not shared
755 * TODO: What should be done for non-memory objects
756 */
757 if ( CLIPBOARD_IsMemoryObject(wFormat) && hData && !(GlobalFlags(hData) & GMEM_DDESHARE) )
758 lpFormat->hData32 = CLIPBOARD_GlobalDupMem( hData );
759 else
Noel Borthwick29700671999-09-03 15:17:57 +0000760 lpFormat->hData32 = hData; /* 0 is legal, see WM_RENDERFORMAT */
Noel Borthwick83579c81999-07-24 12:18:04 +0000761
Pascal Cuoq724f1901998-10-26 10:58:16 +0000762 lpFormat->hData16 = 0;
763
Noel Borthwick29700671999-09-03 15:17:57 +0000764 return lpFormat->hData32; /* Should we return lpFormat->hDataSrc32 */
Alexandre Julliard21979011997-03-05 08:22:35 +0000765}
766
767
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000768/**************************************************************************
Alexandre Julliard21979011997-03-05 08:22:35 +0000769 * GetClipboardData16 (USER.142)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000770 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000771HANDLE16 WINAPI GetClipboardData16( UINT16 wFormat )
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000772{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000773 LPWINE_CLIPFORMAT lpRender = ClipFormats;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000774
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000775 TRACE("(%04X)\n", wFormat);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000776
Noel Borthwick29700671999-09-03 15:17:57 +0000777 if (CLIPBOARD_IsLocked())
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000778 {
Juergen Schmied1c35dae2000-02-07 16:22:57 +0000779 WARN("Clipboard not opened by calling task!\n");
Noel Borthwick29700671999-09-03 15:17:57 +0000780 return 0;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000781 }
Noel Borthwick29700671999-09-03 15:17:57 +0000782
783 if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000784 {
Noel Borthwick29700671999-09-03 15:17:57 +0000785 lpRender = CLIPBOARD_RenderText(wFormat);
786 if ( !lpRender ) return 0;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000787 }
788 else
789 {
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000790 lpRender = __lookup_format( ClipFormats, wFormat );
Noel Borthwick29700671999-09-03 15:17:57 +0000791 if( !lpRender || !CLIPBOARD_RenderFormat(lpRender) ) return 0;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000792 }
793
Noel Borthwick29700671999-09-03 15:17:57 +0000794 /* Convert between 32 -> 16 bit data, if necessary */
Francis Beaudet56ab55d1999-10-24 20:22:24 +0000795 if( lpRender->hData32 && !lpRender->hData16
796 && CLIPBOARD_IsMemoryObject(wFormat) )
Pascal Cuoq724f1901998-10-26 10:58:16 +0000797 {
798 int size;
Noel Borthwick29700671999-09-03 15:17:57 +0000799 if( lpRender->wFormatID == CF_METAFILEPICT )
Pascal Cuoq724f1901998-10-26 10:58:16 +0000800 size = sizeof( METAFILEPICT16 );
801 else
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000802 size = GlobalSize(lpRender->hData32);
803
Noel Borthwick29700671999-09-03 15:17:57 +0000804 lpRender->hData16 = GlobalAlloc16(GMEM_ZEROINIT, size);
805 if( !lpRender->hData16 )
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000806 ERR("(%04X) -- not enough memory in 16b heap\n", wFormat);
Pascal Cuoq724f1901998-10-26 10:58:16 +0000807 else
808 {
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000809 if( lpRender->wFormatID == CF_METAFILEPICT )
810 {
811 FIXME("\timplement function CopyMetaFilePict32to16\n");
812 FIXME("\tin the appropriate file.\n");
813 #ifdef SOMEONE_IMPLEMENTED_ME
814 CopyMetaFilePict32to16( GlobalLock16(lpRender->hData16),
815 GlobalLock(lpRender->hData32) );
816 #endif
817 }
818 else
819 {
820 memcpy( GlobalLock16(lpRender->hData16),
821 GlobalLock(lpRender->hData32),
822 size );
823 }
Noel Borthwick29700671999-09-03 15:17:57 +0000824 GlobalUnlock16(lpRender->hData16);
825 GlobalUnlock(lpRender->hData32);
Pascal Cuoq724f1901998-10-26 10:58:16 +0000826 }
827 }
828
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000829 TRACE("\treturning %04x (type %i)\n",
Noel Borthwick29700671999-09-03 15:17:57 +0000830 lpRender->hData16, lpRender->wFormatID);
831 return lpRender->hData16;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000832}
833
834
835/**************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000836 * GetClipboardData (USER32.222)
Alexandre Julliard21979011997-03-05 08:22:35 +0000837 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000838HANDLE WINAPI GetClipboardData( UINT wFormat )
Alexandre Julliard21979011997-03-05 08:22:35 +0000839{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000840 LPWINE_CLIPFORMAT lpRender = ClipFormats;
Pascal Cuoq724f1901998-10-26 10:58:16 +0000841
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000842 TRACE("(%08X)\n", wFormat);
Pascal Cuoq724f1901998-10-26 10:58:16 +0000843
Noel Borthwick29700671999-09-03 15:17:57 +0000844 if (CLIPBOARD_IsLocked())
Pascal Cuoq724f1901998-10-26 10:58:16 +0000845 {
Noel Borthwick29700671999-09-03 15:17:57 +0000846 WARN("Clipboard not opened by calling task!");
847 return 0;
Pascal Cuoq724f1901998-10-26 10:58:16 +0000848 }
Noel Borthwick29700671999-09-03 15:17:57 +0000849
850 if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
Pascal Cuoq724f1901998-10-26 10:58:16 +0000851 {
Noel Borthwick29700671999-09-03 15:17:57 +0000852 lpRender = CLIPBOARD_RenderText(wFormat);
853 if ( !lpRender ) return 0;
Pascal Cuoq724f1901998-10-26 10:58:16 +0000854 }
855 else
856 {
857 lpRender = __lookup_format( ClipFormats, wFormat );
Noel Borthwick29700671999-09-03 15:17:57 +0000858 if( !lpRender || !CLIPBOARD_RenderFormat(lpRender) ) return 0;
Pascal Cuoq724f1901998-10-26 10:58:16 +0000859 }
860
Noel Borthwick29700671999-09-03 15:17:57 +0000861 /* Convert between 16 -> 32 bit data, if necessary */
Francis Beaudet56ab55d1999-10-24 20:22:24 +0000862 if( lpRender->hData16 && !lpRender->hData32
863 && CLIPBOARD_IsMemoryObject(wFormat) )
Pascal Cuoq724f1901998-10-26 10:58:16 +0000864 {
865 int size;
Noel Borthwick29700671999-09-03 15:17:57 +0000866 if( lpRender->wFormatID == CF_METAFILEPICT )
Alexandre Julliarda3960291999-02-26 11:11:13 +0000867 size = sizeof( METAFILEPICT );
Pascal Cuoq724f1901998-10-26 10:58:16 +0000868 else
Noel Borthwick29700671999-09-03 15:17:57 +0000869 size = GlobalSize16(lpRender->hData16);
870 lpRender->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE,
Noel Borthwick83579c81999-07-24 12:18:04 +0000871 size);
Noel Borthwick29700671999-09-03 15:17:57 +0000872 if( lpRender->wFormatID == CF_METAFILEPICT )
Pascal Cuoq724f1901998-10-26 10:58:16 +0000873 {
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000874 FIXME("\timplement function CopyMetaFilePict16to32\n");
875 FIXME("\tin the appropriate file.\n");
Pascal Cuoq724f1901998-10-26 10:58:16 +0000876#ifdef SOMEONE_IMPLEMENTED_ME
Noel Borthwick29700671999-09-03 15:17:57 +0000877 CopyMetaFilePict16to32( GlobalLock16(lpRender->hData32),
878 GlobalLock(lpRender->hData16) );
Pascal Cuoq724f1901998-10-26 10:58:16 +0000879#endif
880 }
881 else
882 {
Noel Borthwick29700671999-09-03 15:17:57 +0000883 memcpy( GlobalLock(lpRender->hData32),
884 GlobalLock16(lpRender->hData16),
Pascal Cuoq724f1901998-10-26 10:58:16 +0000885 size );
886 }
Noel Borthwick29700671999-09-03 15:17:57 +0000887 GlobalUnlock(lpRender->hData32);
888 GlobalUnlock16(lpRender->hData16);
Pascal Cuoq724f1901998-10-26 10:58:16 +0000889 }
890
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000891 TRACE("\treturning %04x (type %i)\n",
Noel Borthwick29700671999-09-03 15:17:57 +0000892 lpRender->hData32, lpRender->wFormatID);
893 return lpRender->hData32;
Alexandre Julliard21979011997-03-05 08:22:35 +0000894}
895
Noel Borthwick29700671999-09-03 15:17:57 +0000896
Alexandre Julliard21979011997-03-05 08:22:35 +0000897/**************************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000898 * CountClipboardFormats16 (USER.143)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000899 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000900INT16 WINAPI CountClipboardFormats16(void)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000901{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000902 return CountClipboardFormats();
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000903}
904
905
906/**************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000907 * CountClipboardFormats (USER32.63)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000908 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000909INT WINAPI CountClipboardFormats(void)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000910{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000911 INT FormatCount = 0;
912 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000913
Noel Borthwick29700671999-09-03 15:17:57 +0000914 TRACE("()\n");
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000915
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000916 while(TRUE)
917 {
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000918 if (lpFormat == NULL) break;
Alex Korobka44a1b591999-04-01 12:03:52 +0000919
Noel Borthwick29700671999-09-03 15:17:57 +0000920 if( lpFormat->wFormatID != CF_TEXT ) /* Don't count CF_TEXT */
921 {
922 /*
923 * The format is available if either:
924 * 1. The data is already in the cache.
925 * 2. The selection is not owned by us(WINE) and the data is
926 * available to the clipboard driver.
927 */
928 if ( lpFormat->wDataPresent ||
Alexandre Julliard42d20f92000-08-10 01:16:19 +0000929 ( !USER_Driver.pIsSelectionOwner()
930 && USER_Driver.pIsClipboardFormatAvailable( lpFormat->wFormatID ) ) )
Noel Borthwick29700671999-09-03 15:17:57 +0000931 {
Juergen Schmied1c35dae2000-02-07 16:22:57 +0000932 TRACE("\tdata found for format 0x%04x(%s)\n",
Noel Borthwick29700671999-09-03 15:17:57 +0000933 lpFormat->wFormatID, CLIPBOARD_GetFormatName(lpFormat->wFormatID));
934 FormatCount++;
935 }
936 }
937
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000938 lpFormat = lpFormat->NextFormat;
939 }
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000940
Alex Korobka44a1b591999-04-01 12:03:52 +0000941 /* these two are equivalent, adjust the total */
942
943 FormatCount += abs(ClipFormats[CF_TEXT-1].wDataPresent -
944 ClipFormats[CF_OEMTEXT-1].wDataPresent);
945
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000946 TRACE("\ttotal %d\n", FormatCount);
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000947 return FormatCount;
948}
949
950
951/**************************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000952 * EnumClipboardFormats16 (USER.144)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000953 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000954UINT16 WINAPI EnumClipboardFormats16( UINT16 wFormat )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000955{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000956 return EnumClipboardFormats( wFormat );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000957}
958
959
960/**************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000961 * EnumClipboardFormats (USER32.179)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000962 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000963UINT WINAPI EnumClipboardFormats( UINT wFormat )
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000964{
Noel Borthwick29700671999-09-03 15:17:57 +0000965 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
966 BOOL bFormatPresent;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000967
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000968 TRACE("(%04X)\n", wFormat);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000969
Noel Borthwick29700671999-09-03 15:17:57 +0000970 if (CLIPBOARD_IsLocked())
971 {
972 WARN("Clipboard not opened by calling task!");
973 return 0;
974 }
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000975
Alex Korobka44a1b591999-04-01 12:03:52 +0000976 if (wFormat == 0) /* start from the beginning */
977 lpFormat = ClipFormats;
978 else
Jesper Skov5c3e4571998-11-01 19:27:22 +0000979 {
Alex Korobka44a1b591999-04-01 12:03:52 +0000980 /* walk up to the specified format record */
981
982 if( !(lpFormat = __lookup_format( lpFormat, wFormat )) )
983 return 0;
984 lpFormat = lpFormat->NextFormat; /* right */
Jesper Skov5c3e4571998-11-01 19:27:22 +0000985 }
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000986
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000987 while(TRUE)
988 {
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000989 if (lpFormat == NULL) return 0;
Alex Korobka44a1b591999-04-01 12:03:52 +0000990
Noel Borthwick29700671999-09-03 15:17:57 +0000991 /* Synthesize CF_TEXT from CF_OEMTEXT and vice versa */
992 bFormatPresent = (lpFormat->wDataPresent ||
993 (lpFormat->wFormatID == CF_OEMTEXT && ClipFormats[CF_TEXT-1].wDataPresent) ||
994 (lpFormat->wFormatID == CF_TEXT && ClipFormats[CF_OEMTEXT-1].wDataPresent) );
Alex Korobka44a1b591999-04-01 12:03:52 +0000995
Noel Borthwick29700671999-09-03 15:17:57 +0000996 /* Query the driver if not yet in the cache */
Alexandre Julliard42d20f92000-08-10 01:16:19 +0000997 if (!bFormatPresent && !USER_Driver.pIsSelectionOwner())
Noel Borthwick29700671999-09-03 15:17:57 +0000998 {
999 bFormatPresent =
Alexandre Julliard42d20f92000-08-10 01:16:19 +00001000 USER_Driver.pIsClipboardFormatAvailable( (lpFormat->wFormatID == CF_TEXT) ?
Noel Borthwick29700671999-09-03 15:17:57 +00001001 CF_OEMTEXT : lpFormat->wFormatID );
1002 }
1003
1004 if (bFormatPresent)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001005 break;
Noel Borthwick29700671999-09-03 15:17:57 +00001006
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001007 lpFormat = lpFormat->NextFormat;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001008 }
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001009
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001010 return lpFormat->wFormatID;
1011}
1012
1013
1014/**************************************************************************
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001015 * RegisterClipboardFormat16 (USER.145)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001016 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001017UINT16 WINAPI RegisterClipboardFormat16( LPCSTR FormatName )
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001018{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001019 LPWINE_CLIPFORMAT lpNewFormat;
1020 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001021
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001022 if (FormatName == NULL) return 0;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001023
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001024 TRACE("('%s') !\n", FormatName);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001025
1026 /* walk format chain to see if it's already registered */
1027
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001028 while(TRUE)
1029 {
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001030 if ( !strcmp(lpFormat->Name,FormatName) )
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001031 {
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001032 lpFormat->wRefCount++;
1033 return lpFormat->wFormatID;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001034 }
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001035
1036 if ( lpFormat->NextFormat == NULL ) break;
1037
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001038 lpFormat = lpFormat->NextFormat;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001039 }
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001040
1041 /* allocate storage for new format entry */
1042
Dimitrie O. Paun9ad96362000-03-19 14:29:50 +00001043 lpNewFormat = (LPWINE_CLIPFORMAT)HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_CLIPFORMAT));
1044 if(lpNewFormat == NULL) {
1045 WARN("No more memory for a new format!");
1046 return 0;
1047 }
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001048 lpFormat->NextFormat = lpNewFormat;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001049 lpNewFormat->wFormatID = LastRegFormat;
1050 lpNewFormat->wRefCount = 1;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001051
Dimitrie O. Paun9ad96362000-03-19 14:29:50 +00001052 lpNewFormat->Name = (LPSTR)HEAP_strdupA(GetProcessHeap(), 0, FormatName);
1053 if(lpNewFormat->Name == NULL) {
1054 WARN("No more memory for the new format name!");
1055 HeapFree(GetProcessHeap(), 0, lpNewFormat);
1056 return 0;
1057 }
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001058
1059 lpNewFormat->wDataPresent = 0;
Pascal Cuoq724f1901998-10-26 10:58:16 +00001060 lpNewFormat->hData16 = 0;
Noel Borthwick83579c81999-07-24 12:18:04 +00001061 lpNewFormat->hDataSrc32 = 0;
Pascal Cuoq724f1901998-10-26 10:58:16 +00001062 lpNewFormat->hData32 = 0;
Noel Borthwick29700671999-09-03 15:17:57 +00001063 lpNewFormat->drvData = 0;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001064 lpNewFormat->PrevFormat = lpFormat;
1065 lpNewFormat->NextFormat = NULL;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001066
Noel Borthwick29700671999-09-03 15:17:57 +00001067 /* Pass on the registration request to the driver */
Alexandre Julliard42d20f92000-08-10 01:16:19 +00001068 USER_Driver.pRegisterClipboardFormat( FormatName );
Noel Borthwick29700671999-09-03 15:17:57 +00001069
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001070 return LastRegFormat++;
1071}
1072
1073
1074/**************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001075 * RegisterClipboardFormatA (USER32.431)
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001076 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001077UINT WINAPI RegisterClipboardFormatA( LPCSTR formatName )
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001078{
1079 return RegisterClipboardFormat16( formatName );
1080}
1081
1082
1083/**************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001084 * RegisterClipboardFormatW (USER32.432)
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001085 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001086UINT WINAPI RegisterClipboardFormatW( LPCWSTR formatName )
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001087{
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001088 LPSTR aFormat = HEAP_strdupWtoA( GetProcessHeap(), 0, formatName );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001089 UINT ret = RegisterClipboardFormatA( aFormat );
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001090 HeapFree( GetProcessHeap(), 0, aFormat );
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001091 return ret;
1092}
1093
Noel Borthwick29700671999-09-03 15:17:57 +00001094
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001095/**************************************************************************
Alexandre Julliard21979011997-03-05 08:22:35 +00001096 * GetClipboardFormatName16 (USER.146)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001097 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001098INT16 WINAPI GetClipboardFormatName16( UINT16 wFormat, LPSTR retStr, INT16 maxlen )
Alexandre Julliard21979011997-03-05 08:22:35 +00001099{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001100 return GetClipboardFormatNameA( wFormat, retStr, maxlen );
Alexandre Julliard21979011997-03-05 08:22:35 +00001101}
1102
1103
1104/**************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001105 * GetClipboardFormatNameA (USER32.223)
Alexandre Julliard21979011997-03-05 08:22:35 +00001106 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001107INT WINAPI GetClipboardFormatNameA( UINT wFormat, LPSTR retStr, INT maxlen )
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001108{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001109 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001110
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001111 TRACE("(%04X, %p, %d) !\n", wFormat, retStr, maxlen);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001112
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001113 if (lpFormat == NULL || lpFormat->Name == NULL ||
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001114 lpFormat->wFormatID < CF_REGFORMATBASE) return 0;
1115
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001116 TRACE("Name='%s' !\n", lpFormat->Name);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001117
Alexandre Julliarda3960291999-02-26 11:11:13 +00001118 lstrcpynA( retStr, lpFormat->Name, maxlen );
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001119 return strlen(retStr);
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001120}
1121
1122
1123/**************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001124 * GetClipboardFormatNameW (USER32.224)
Alexandre Julliard21979011997-03-05 08:22:35 +00001125 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001126INT WINAPI GetClipboardFormatNameW( UINT wFormat, LPWSTR retStr, INT maxlen )
Alexandre Julliard21979011997-03-05 08:22:35 +00001127{
Dimitrie O. Paun4d48dd32000-04-30 12:22:18 +00001128 INT ret;
1129 LPSTR p = HeapAlloc( GetProcessHeap(), 0, maxlen );
1130 if(p == NULL) return 0; /* FIXME: is this the correct failure value? */
1131
1132 ret = GetClipboardFormatNameA( wFormat, p, maxlen );
Alexandre Julliard21979011997-03-05 08:22:35 +00001133 lstrcpynAtoW( retStr, p, maxlen );
1134 HeapFree( GetProcessHeap(), 0, p );
1135 return ret;
1136}
1137
1138
1139/**************************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001140 * SetClipboardViewer16 (USER.147)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001141 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001142HWND16 WINAPI SetClipboardViewer16( HWND16 hWnd )
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001143{
Noel Borthwick29700671999-09-03 15:17:57 +00001144 TRACE("(%04x)\n", hWnd);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001145 return SetClipboardViewer( hWnd );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001146}
1147
1148
1149/**************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001150 * SetClipboardViewer (USER32.471)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001151 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001152HWND WINAPI SetClipboardViewer( HWND hWnd )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001153{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001154 HWND hwndPrev = hWndViewer;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001155
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001156 TRACE("(%04x): returning %04x\n", hWnd, hwndPrev);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001157
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001158 hWndViewer = hWnd;
Alexandre Julliardecc37121994-11-22 16:31:29 +00001159 return hwndPrev;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001160}
1161
1162
1163/**************************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001164 * GetClipboardViewer16 (USER.148)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001165 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001166HWND16 WINAPI GetClipboardViewer16(void)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001167{
Noel Borthwick29700671999-09-03 15:17:57 +00001168 TRACE("()\n");
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001169 return hWndViewer;
1170}
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001171
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001172
1173/**************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001174 * GetClipboardViewer (USER32.226)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001175 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001176HWND WINAPI GetClipboardViewer(void)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001177{
Noel Borthwick29700671999-09-03 15:17:57 +00001178 TRACE("()\n");
Alexandre Julliardaca05781994-10-17 18:12:41 +00001179 return hWndViewer;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001180}
1181
1182
1183/**************************************************************************
Alexandre Julliard21979011997-03-05 08:22:35 +00001184 * ChangeClipboardChain16 (USER.149)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001185 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001186BOOL16 WINAPI ChangeClipboardChain16(HWND16 hWnd, HWND16 hWndNext)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001187{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001188 return ChangeClipboardChain(hWnd, hWndNext);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001189}
1190
Noel Borthwick29700671999-09-03 15:17:57 +00001191
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001192/**************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001193 * ChangeClipboardChain (USER32.22)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001194 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001195BOOL WINAPI ChangeClipboardChain(HWND hWnd, HWND hWndNext)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001196{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001197 BOOL bRet = 0;
Alexandre Julliard234bc241994-12-10 13:02:28 +00001198
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001199 FIXME("(0x%04x, 0x%04x): stub?\n", hWnd, hWndNext);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001200
1201 if( hWndViewer )
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001202 bRet = !SendMessage16( hWndViewer, WM_CHANGECBCHAIN,
Alexandre Julliard530ee841996-10-23 16:59:13 +00001203 (WPARAM16)hWnd, (LPARAM)hWndNext);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001204 else
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001205 WARN("hWndViewer is lost\n");
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001206
1207 if( hWnd == hWndViewer ) hWndViewer = hWndNext;
1208
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001209 return bRet;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001210}
1211
1212
1213/**************************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001214 * IsClipboardFormatAvailable16 (USER.193)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001215 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001216BOOL16 WINAPI IsClipboardFormatAvailable16( UINT16 wFormat )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001217{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001218 return IsClipboardFormatAvailable( wFormat );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001219}
1220
1221
1222/**************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001223 * IsClipboardFormatAvailable (USER32.340)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001224 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001225BOOL WINAPI IsClipboardFormatAvailable( UINT wFormat )
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001226{
Noel Borthwick29700671999-09-03 15:17:57 +00001227 BOOL bRet;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001228
Noel Borthwick29700671999-09-03 15:17:57 +00001229 if (wFormat == 0) /* Reject this case quickly */
1230 bRet = FALSE;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001231
Noel Borthwick29700671999-09-03 15:17:57 +00001232 /* If WINE is not the clipboard selection owner ask the clipboard driver */
Alexandre Julliard42d20f92000-08-10 01:16:19 +00001233 else if ( !USER_Driver.pIsSelectionOwner() )
1234 bRet = USER_Driver.pIsClipboardFormatAvailable( (wFormat == CF_TEXT) ?
Noel Borthwick29700671999-09-03 15:17:57 +00001235 CF_OEMTEXT : wFormat );
1236 /* Check if the format is in the local cache */
1237 else
1238 bRet = CLIPBOARD_IsPresent(wFormat);
1239
1240 TRACE("(%04X)- ret(%d)\n", wFormat, bRet);
1241 return bRet;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001242}
1243
1244
1245/**************************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001246 * GetOpenClipboardWindow16 (USER.248)
Noel Borthwick29700671999-09-03 15:17:57 +00001247 * FIXME: This wont work if an external app owns the selection
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001248 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001249HWND16 WINAPI GetOpenClipboardWindow16(void)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001250{
Noel Borthwick29700671999-09-03 15:17:57 +00001251 TRACE("()\n");
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001252 return hWndClipWindow;
1253}
1254
1255
1256/**************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001257 * GetOpenClipboardWindow (USER32.277)
Noel Borthwick29700671999-09-03 15:17:57 +00001258 * FIXME: This wont work if an external app owns the selection
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001259 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001260HWND WINAPI GetOpenClipboardWindow(void)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001261{
Noel Borthwick29700671999-09-03 15:17:57 +00001262 TRACE("()\n");
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001263 return hWndClipWindow;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001264}
1265
1266
1267/**************************************************************************
Alexandre Julliard21979011997-03-05 08:22:35 +00001268 * GetPriorityClipboardFormat16 (USER.402)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001269 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001270INT16 WINAPI GetPriorityClipboardFormat16( UINT16 *lpPriorityList, INT16 nCount)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001271{
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001272 FIXME("(%p,%d): stub\n", lpPriorityList, nCount );
Alexandre Julliard21979011997-03-05 08:22:35 +00001273 return 0;
1274}
Alexandre Julliard234bc241994-12-10 13:02:28 +00001275
Alexandre Julliard21979011997-03-05 08:22:35 +00001276
1277/**************************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00001278 * GetPriorityClipboardFormat (USER32.279)
Alexandre Julliard21979011997-03-05 08:22:35 +00001279 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001280INT WINAPI GetPriorityClipboardFormat( UINT *lpPriorityList, INT nCount )
Alexandre Julliard21979011997-03-05 08:22:35 +00001281{
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001282 int Counter;
Noel Borthwick29700671999-09-03 15:17:57 +00001283 TRACE("()\n");
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001284
Alexandre Julliarda3960291999-02-26 11:11:13 +00001285 if(CountClipboardFormats() == 0)
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001286 {
1287 return 0;
1288 }
1289
1290 for(Counter = 0; Counter <= nCount; Counter++)
1291 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001292 if(IsClipboardFormatAvailable(*(lpPriorityList+sizeof(INT)*Counter)))
1293 return *(lpPriorityList+sizeof(INT)*Counter);
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001294 }
1295
1296 return -1;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001297}
1298