blob: 27fe04bb622a519621ca037f96824a721fd44aae [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>
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"
Marcus Meissner61afa331999-02-22 10:16:00 +000030#include "message.h"
Noel Borthwick29700671999-09-03 15:17:57 +000031#include "task.h"
32#include "queue.h"
Alexandre Julliard234bc241994-12-10 13:02:28 +000033#include "clipboard.h"
Alexandre Julliard1e9ac791996-06-06 18:38:27 +000034#include "xmalloc.h"
Alexandre Julliard359f497e1999-07-04 16:02:24 +000035#include "debugtools.h"
Alexandre Julliardfb9a9191994-03-01 19:48:04 +000036
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000037DEFAULT_DEBUG_CHANNEL(clipboard)
38
Alexandre Julliard1e9ac791996-06-06 18:38:27 +000039#define CF_REGFORMATBASE 0xC000
40
Patrik Stridvalle35d6361998-12-07 09:13:40 +000041/**************************************************************************
Noel Borthwick29700671999-09-03 15:17:57 +000042 * Clipboard context global variables
Alexandre Julliard1e9ac791996-06-06 18:38:27 +000043 */
44
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +000045CLIPBOARD_DRIVER *CLIPBOARD_Driver = NULL;
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 */
Alexandre Julliarda3960291999-02-26 11:11:13 +000061WINE_CLIPFORMAT ClipFormats[16] = {
Noel Borthwick29700671999-09-03 15:17:57 +000062 { CF_TEXT, 1, 0, "Text", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, NULL, &ClipFormats[1]},
63 { CF_BITMAP, 1, 0, "Bitmap", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[0], &ClipFormats[2]},
64 { CF_METAFILEPICT, 1, 0, "MetaFile Picture", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[1], &ClipFormats[3]},
65 { CF_SYLK, 1, 0, "Sylk", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[2], &ClipFormats[4]},
66 { CF_DIF, 1, 0, "DIF", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[3], &ClipFormats[5]},
67 { CF_TIFF, 1, 0, "TIFF", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[4], &ClipFormats[6]},
68 { CF_OEMTEXT, 1, 0, "OEM Text", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[5], &ClipFormats[7]},
69 { CF_DIB, 1, 0, "DIB", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[6], &ClipFormats[8]},
70 { CF_PALETTE, 1, 0, "Palette", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[7], &ClipFormats[9]},
71 { CF_PENDATA, 1, 0, "PenData", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[8], &ClipFormats[10]},
72 { CF_RIFF, 1, 0, "RIFF", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[9], &ClipFormats[11]},
73 { CF_WAVE, 1, 0, "Wave", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[10], &ClipFormats[12]},
74 { CF_OWNERDISPLAY, 1, 0, "Owner Display", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[11], &ClipFormats[13]},
75 { CF_DSPTEXT, 1, 0, "DSPText", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[12], &ClipFormats[14]},
76 { CF_DSPMETAFILEPICT, 1, 0, "DSPMetaFile Picture", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[13], &ClipFormats[15]},
77 { CF_DSPBITMAP, 1, 0, "DSPBitmap", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[14], NULL}
Alexandre Julliardfb9a9191994-03-01 19:48:04 +000078 };
79
Noel Borthwick29700671999-09-03 15:17:57 +000080
81/**************************************************************************
82 * Internal Clipboard implementation methods
83 **************************************************************************/
84
85
86/**************************************************************************
87 * CLIPBOARD_LookupFormat
88 */
Alexandre Julliarda3960291999-02-26 11:11:13 +000089static LPWINE_CLIPFORMAT __lookup_format( LPWINE_CLIPFORMAT lpFormat, WORD wID )
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +000090{
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +000091 while(TRUE)
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +000092 {
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +000093 if (lpFormat == NULL ||
94 lpFormat->wFormatID == wID) break;
95 lpFormat = lpFormat->NextFormat;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +000096 }
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +000097 return lpFormat;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +000098}
99
Noel Borthwick29700671999-09-03 15:17:57 +0000100LPWINE_CLIPFORMAT CLIPBOARD_LookupFormat( WORD wID )
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000101{
Noel Borthwick29700671999-09-03 15:17:57 +0000102 return __lookup_format( ClipFormats, wID );
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000103}
104
Noel Borthwick29700671999-09-03 15:17:57 +0000105/**************************************************************************
106 * CLIPBOARD_IsLocked
107 * Check if the clipboard cache is available to the caller
108 */
109BOOL CLIPBOARD_IsLocked()
110{
111 BOOL bIsLocked = TRUE;
112 HANDLE16 hTaskCur = GetCurrentTask();
113
114 /*
115 * The clipboard is available:
116 * 1. if the caller's task has opened the clipboard,
117 * or
118 * 2. if the caller is the clipboard owners task, AND is responding to a
119 * WM_RENDERFORMAT message.
120 */
121 if ( hClipLock == hTaskCur )
122 bIsLocked = FALSE;
123
124 else if ( hTaskCur == hTaskClipOwner )
125 {
126 /* Check if we're currently executing inside a window procedure
127 * called in response to a WM_RENDERFORMAT message. A WM_RENDERFORMAT
128 * handler is not permitted to open the clipboard since it has been opened
129 * by another client. However the handler must have access to the
130 * clipboard in order to update data in response to this message.
131 */
132 MESSAGEQUEUE *queue = QUEUE_Lock( GetFastQueue16() );
133
134 if ( queue
135 && queue->smWaiting
136 && queue->smWaiting->msg == WM_RENDERFORMAT
137 && queue->smWaiting->hSrcQueue
138 )
139 bIsLocked = FALSE;
140
141 QUEUE_Unlock( queue );
142 }
143
144 return bIsLocked;
145}
146
147/**************************************************************************
148 * CLIPBOARD_ReleaseOwner
149 * Gives up ownership of the clipboard
150 */
151void CLIPBOARD_ReleaseOwner()
152{
153 hWndClipOwner = 0;
154 hTaskClipOwner = 0;
155}
156
157/**************************************************************************
158 * CLIPBOARD_GlobalFreeProc
159 *
160 * This is a callback mechanism to allow HGLOBAL data to be released in
161 * the context of the process which allocated it. We post a WM_TIMER message
162 * to the owner window(in CLIPBOARD_DeleteRecord) and destroy the data(in idEvent)
163 * in this WndProc, which is invoked when the apps message loop calls DispatchMessage.
164 * This technique is discussed in Matt Pietrek's "Under the Hood".
165 * An article describing the same may be found in MSDN by searching for WM_TIMER.
166 * Note that this mechanism will probably stop working when WINE supports
167 * address space separation. When "queue events" are implemented in Wine we
168 * should switch to using that mechanism, since it is more robust and does not
169 * require a procedure address to be passed. See the SetWinEventHook API for
170 * more info on this.
171 */
172VOID CALLBACK CLIPBOARD_GlobalFreeProc( HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime )
173{
174 /* idEvent is the HGLOBAL to be deleted */
175 GlobalFree( (HGLOBAL)idEvent );
176}
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000177
178/**************************************************************************
179 * CLIPBOARD_DeleteRecord
180 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000181void CLIPBOARD_DeleteRecord(LPWINE_CLIPFORMAT lpFormat, BOOL bChange)
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000182{
Alexandre Julliard03468f71998-02-15 19:40:49 +0000183 if( (lpFormat->wFormatID >= CF_GDIOBJFIRST &&
Ulrich Czekalla6623b851999-10-23 14:10:04 +0000184 lpFormat->wFormatID <= CF_GDIOBJLAST) || lpFormat->wFormatID == CF_BITMAP
185 || lpFormat->wFormatID == CF_PALETTE)
Alexandre Julliard03468f71998-02-15 19:40:49 +0000186 {
Pascal Cuoq724f1901998-10-26 10:58:16 +0000187 if (lpFormat->hData32)
Alexandre Julliarda3960291999-02-26 11:11:13 +0000188 DeleteObject(lpFormat->hData32);
Pascal Cuoq724f1901998-10-26 10:58:16 +0000189 if (lpFormat->hData16)
190 DeleteObject16(lpFormat->hData16);
Alexandre Julliard03468f71998-02-15 19:40:49 +0000191 }
Pascal Cuoq724f1901998-10-26 10:58:16 +0000192 else if( lpFormat->wFormatID == CF_METAFILEPICT )
193 {
194 if (lpFormat->hData32)
195 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000196 DeleteMetaFile( ((METAFILEPICT *)GlobalLock( lpFormat->hData32 ))->hMF );
Noel Borthwick29700671999-09-03 15:17:57 +0000197 PostMessageA(hWndClipOwner, WM_TIMER,
198 (WPARAM)lpFormat->hData32, (LPARAM)CLIPBOARD_GlobalFreeProc);
Noel Borthwick83579c81999-07-24 12:18:04 +0000199 if (lpFormat->hDataSrc32)
Noel Borthwick29700671999-09-03 15:17:57 +0000200 {
201 /* Release lpFormat->hData32 in the context of the process which created it.
202 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
203 * GlobalFree(lpFormat->hDataSrc32);
204 */
205 PostMessageA(hWndClipOwner, WM_TIMER,
206 (WPARAM)lpFormat->hDataSrc32, (LPARAM)CLIPBOARD_GlobalFreeProc);
207 }
208
Pascal Cuoq724f1901998-10-26 10:58:16 +0000209 if (lpFormat->hData16)
210 /* HMETAFILE16 and HMETAFILE32 are apparently the same thing,
211 and a shallow copy is enough to share a METAFILEPICT
212 structure between 16bit and 32bit clipboards. The MetaFile
213 should of course only be deleted once. */
214 GlobalFree16(lpFormat->hData16);
215 }
Noel Borthwick83579c81999-07-24 12:18:04 +0000216 if (lpFormat->hData16)
Pascal Cuoq724f1901998-10-26 10:58:16 +0000217 {
218 DeleteMetaFile16( ((METAFILEPICT16 *)GlobalLock16( lpFormat->hData16 ))->hMF );
219 GlobalFree16(lpFormat->hData16);
220 }
221 }
222 else
223 {
224 if (lpFormat->hData32)
Noel Borthwick29700671999-09-03 15:17:57 +0000225 {
226 /* Release lpFormat->hData32 in the context of the process which created it.
227 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
228 * GlobalFree( lpFormat->hData32 );
229 */
230 PostMessageA(hWndClipOwner, WM_TIMER,
231 (WPARAM)lpFormat->hData32, (LPARAM)CLIPBOARD_GlobalFreeProc);
232 }
Noel Borthwick83579c81999-07-24 12:18:04 +0000233 if (lpFormat->hDataSrc32)
Noel Borthwick29700671999-09-03 15:17:57 +0000234 {
235 /* Release lpFormat->hData32 in the context of the process which created it.
236 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
237 * GlobalFree(lpFormat->hDataSrc32);
238 */
239 PostMessageA(hWndClipOwner, WM_TIMER,
240 (WPARAM)lpFormat->hDataSrc32, (LPARAM)CLIPBOARD_GlobalFreeProc);
241 }
Pascal Cuoq724f1901998-10-26 10:58:16 +0000242 if (lpFormat->hData16)
243 GlobalFree16(lpFormat->hData16);
244 }
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000245
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000246 lpFormat->wDataPresent = 0;
Pascal Cuoq724f1901998-10-26 10:58:16 +0000247 lpFormat->hData16 = 0;
248 lpFormat->hData32 = 0;
Noel Borthwick29700671999-09-03 15:17:57 +0000249 lpFormat->hDataSrc32 = 0;
250 lpFormat->drvData = 0;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000251
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000252 if( bChange ) bCBHasChanged = TRUE;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000253}
254
255/**************************************************************************
Noel Borthwick29700671999-09-03 15:17:57 +0000256 * CLIPBOARD_EmptyCache
257 */
258void CLIPBOARD_EmptyCache( BOOL bChange )
259{
260 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
261
262 while(lpFormat)
263 {
264 if ( lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32 )
265 CLIPBOARD_DeleteRecord( lpFormat, bChange );
266
267 lpFormat = lpFormat->NextFormat;
268 }
269}
270
271/**************************************************************************
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000272 * CLIPBOARD_IsPresent
273 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000274BOOL CLIPBOARD_IsPresent(WORD wFormat)
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000275{
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000276 /* special case */
277
278 if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000279 return ClipFormats[CF_TEXT-1].wDataPresent ||
280 ClipFormats[CF_OEMTEXT-1].wDataPresent;
281 else
282 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000283 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000284 if( lpFormat ) return (lpFormat->wDataPresent);
285 }
286 return FALSE;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000287}
288
289/**************************************************************************
Noel Borthwick29700671999-09-03 15:17:57 +0000290 * CLIPBOARD_IsCacheRendered
291 * Checks if any data needs to be rendered to the clipboard cache
292 * RETURNS:
293 * TRUE - All clipboard data is available in the cache
294 * FALSE - Some data is marked for delayed render and needs rendering
295 */
296BOOL CLIPBOARD_IsCacheRendered()
297{
298 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
299
300 /* check if all formats were rendered */
301 while(lpFormat)
302 {
303 if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
304 return FALSE;
305
306 lpFormat = lpFormat->NextFormat;
307 }
308
309 return TRUE;
310}
311
312
313/**************************************************************************
Noel Borthwick83579c81999-07-24 12:18:04 +0000314 * CLIPBOARD_IsMemoryObject
315 * Tests if the clipboard format specifies a memory object
316 */
317BOOL CLIPBOARD_IsMemoryObject( WORD wFormat )
318{
319 switch(wFormat)
320 {
321 case CF_BITMAP:
322 case CF_METAFILEPICT:
323 case CF_DSPTEXT:
324 case CF_ENHMETAFILE:
325 case CF_HDROP:
326 case CF_PALETTE:
327 case CF_PENDATA:
328 return FALSE;
329 default:
330 return TRUE;
331 }
332}
333
334/***********************************************************************
335 * CLIPBOARD_GlobalDupMem( HGLOBAL )
336 * Helper method to duplicate an HGLOBAL chunk of memory into shared memory
337 */
338HGLOBAL CLIPBOARD_GlobalDupMem( HGLOBAL hGlobalSrc )
339{
340 HGLOBAL hGlobalDest;
341 PVOID pGlobalSrc, pGlobalDest;
342 DWORD cBytes;
343
344 if ( !hGlobalSrc )
345 return 0;
346
347 cBytes = GlobalSize(hGlobalSrc);
348 if ( 0 == cBytes )
349 return 0;
350
351 /* Turn on the DDESHARE and _MOVEABLE flags explicitly */
352 hGlobalDest = GlobalAlloc( GlobalFlags(hGlobalSrc) | GMEM_DDESHARE | GMEM_MOVEABLE,
353 cBytes );
354 if ( !hGlobalDest )
355 return 0;
356
357 pGlobalSrc = GlobalLock(hGlobalSrc);
358 pGlobalDest = GlobalLock(hGlobalDest);
359 if ( !pGlobalSrc || !pGlobalDest )
360 return 0;
361
362 memcpy(pGlobalDest, pGlobalSrc, cBytes);
363
364 GlobalUnlock(hGlobalSrc);
365 GlobalUnlock(hGlobalDest);
366
367 return hGlobalDest;
368}
369
370/**************************************************************************
Noel Borthwick29700671999-09-03 15:17:57 +0000371 * CLIPBOARD_GetFormatName
372 * Gets the format name associated with an ID
373 */
374char * CLIPBOARD_GetFormatName(UINT wFormat)
375{
376 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
377 return (lpFormat) ? lpFormat->Name : NULL;
378}
379
380
381/**************************************************************************
382 * CLIPBOARD_RenderFormat
383 */
384static BOOL CLIPBOARD_RenderFormat(LPWINE_CLIPFORMAT lpFormat)
385{
386 /*
387 * If WINE is not the selection owner, and the format is available
388 * we must ask the the driver to render the data to the clipboard cache.
389 */
390 if ( !CLIPBOARD_Driver->pIsSelectionOwner()
391 && CLIPBOARD_Driver->pIsFormatAvailable( lpFormat->wFormatID ) )
392 {
393 if ( !CLIPBOARD_Driver->pGetData( lpFormat->wFormatID ) )
394 return FALSE;
395 }
396 /*
397 * If Wine owns the clipboard, and the data is marked for delayed render,
398 * render it now.
399 */
400 else if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
401 {
402 if( IsWindow(hWndClipOwner) )
403 {
404 /* Send a WM_RENDERFORMAT message to notify the owner to render the
405 * data requested into the clipboard.
406 */
407 TRACE("Sending WM_RENDERFORMAT message\n");
408 SendMessage16(hWndClipOwner,WM_RENDERFORMAT,
409 (WPARAM16)lpFormat->wFormatID,0L);
410 }
411 else
412 {
413 WARN("\thWndClipOwner (%04x) is lost!\n",
414 hWndClipOwner);
415 CLIPBOARD_ReleaseOwner();
416 lpFormat->wDataPresent = 0;
417 return FALSE;
418 }
419 }
420
421 return (lpFormat->hData16 || lpFormat->hData32) ? TRUE : FALSE;
422}
423
424
425/**************************************************************************
426 * CLIPBOARD_RenderText
427 *
428 * Renders text to the clipboard buffer converting between UNIX and DOS formats.
429 *
430 * RETURNS: pointer to the WINE_CLIPFORMAT if successful, NULL otherwise
431 *
432 * FIXME: Should be a pair of driver functions that convert between OEM text and Windows.
433 *
434 */
435static LPWINE_CLIPFORMAT CLIPBOARD_RenderText( UINT wFormat )
436{
437 LPWINE_CLIPFORMAT lpSource = ClipFormats;
438 LPWINE_CLIPFORMAT lpTarget;
439
440 /* Asked for CF_TEXT and not available - always attempt to convert from CF_OEM_TEXT */
441 if( wFormat == CF_TEXT && !ClipFormats[CF_TEXT-1].wDataPresent )
442 {
443 /* Convert OEMTEXT -> TEXT */
444 lpSource = &ClipFormats[CF_OEMTEXT-1];
445 lpTarget = &ClipFormats[CF_TEXT-1];
446
447 TRACE("\tOEMTEXT -> TEXT\n");
448 }
449 /* Asked for CF_OEM_TEXT, and CF_TEXT available */
450 else if( wFormat == CF_OEMTEXT && !ClipFormats[CF_OEMTEXT-1].wDataPresent
451 && ClipFormats[CF_TEXT-1].wDataPresent )
452 {
453 /* Convert TEXT -> OEMTEXT */
454 lpSource = &ClipFormats[CF_TEXT-1];
455 lpTarget = &ClipFormats[CF_OEMTEXT-1];
456
457 TRACE("\tTEXT -> OEMTEXT\n");
458 }
459 /* Text format requested is available - no conversion necessary */
460 else
461 {
462 lpSource = __lookup_format( ClipFormats, wFormat );
463 lpTarget = lpSource;
464 }
465
466 /* First render the source text format */
467 if ( !lpSource || !CLIPBOARD_RenderFormat(lpSource) ) return NULL;
468
469 /* Convert to the desired target text format, if necessary */
470 if( lpTarget != lpSource && !lpTarget->hData16 && !lpTarget->hData32 )
471 {
472 UINT16 size;
473 LPCSTR lpstrS;
474 LPSTR lpstrT;
475
476 if (lpSource->hData32)
477 {
478 size = GlobalSize( lpSource->hData32 );
479 lpstrS = (LPSTR)GlobalLock(lpSource->hData32);
480 }
481 else
482 {
483 size = GlobalSize16( lpSource->hData16 );
484 lpstrS = (LPSTR)GlobalLock16(lpSource->hData16);
485 }
486
487 if( !lpstrS ) return NULL;
488 TRACE("\tconverting from '%s' to '%s', %i chars\n",
489 lpSource->Name, lpTarget->Name, size);
490
Francis Beaudet56ab55d1999-10-24 20:22:24 +0000491 lpTarget->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, size);
Noel Borthwick29700671999-09-03 15:17:57 +0000492 lpstrT = (LPSTR)GlobalLock(lpTarget->hData32);
493
494 if( lpstrT )
495 {
496 if( lpSource->wFormatID == CF_TEXT )
497 CharToOemBuffA(lpstrS, lpstrT, size);
498 else
499 OemToCharBuffA(lpstrS, lpstrT, size);
500 TRACE("\tgot %s\n", lpstrT);
501 GlobalUnlock(lpTarget->hData32);
502 }
503 else
504 lpTarget->hData32 = 0;
505
506 /* Unlock source */
507 if (lpSource->hData32)
508 GlobalUnlock(lpSource->hData32);
509 else
510 GlobalUnlock16(lpSource->hData16);
511 }
512
513 return (lpTarget->hData16 || lpTarget->hData32) ? lpTarget : NULL;
514}
515
516/**************************************************************************
517 * WIN32 Clipboard implementation
518 **************************************************************************/
519
520/**************************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000521 * OpenClipboard16 (USER.137)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000522 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000523BOOL16 WINAPI OpenClipboard16( HWND16 hWnd )
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000524{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000525 return OpenClipboard( hWnd );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000526}
527
528
529/**************************************************************************
Alexandre Julliard54c27111998-03-29 19:44:57 +0000530 * OpenClipboard32 (USER32.407)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000531 *
532 * Note: Netscape uses NULL hWnd to open the clipboard.
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000533 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000534BOOL WINAPI OpenClipboard( HWND hWnd )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000535{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000536 BOOL bRet;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000537
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000538 TRACE("(%04x)...\n", hWnd);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000539
Noel Borthwick29700671999-09-03 15:17:57 +0000540 if (!hClipLock)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000541 {
Noel Borthwick29700671999-09-03 15:17:57 +0000542 hClipLock = GetCurrentTask();
543
544 /* Save current user of the clipboard */
545 hWndClipWindow = hWnd;
546 bCBHasChanged = FALSE;
547 bRet = TRUE;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000548 }
549 else bRet = FALSE;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000550
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000551 TRACE(" returning %i\n", bRet);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000552 return bRet;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000553}
554
555
556/**************************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000557 * CloseClipboard16 (USER.138)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000558 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000559BOOL16 WINAPI CloseClipboard16(void)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000560{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000561 return CloseClipboard();
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000562}
563
564
565/**************************************************************************
Alexandre Julliard54c27111998-03-29 19:44:57 +0000566 * CloseClipboard32 (USER32.54)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000567 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000568BOOL WINAPI CloseClipboard(void)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000569{
Noel Borthwick29700671999-09-03 15:17:57 +0000570 TRACE("()\n");
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000571
Noel Borthwick29700671999-09-03 15:17:57 +0000572 if (hClipLock == GetCurrentTask())
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000573 {
574 hWndClipWindow = 0;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000575
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000576 if (bCBHasChanged && hWndViewer)
577 SendMessage16(hWndViewer, WM_DRAWCLIPBOARD, 0, 0L);
Noel Borthwick29700671999-09-03 15:17:57 +0000578 hClipLock = 0;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000579 }
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000580 return TRUE;
581}
582
583
584/**************************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000585 * EmptyClipboard16 (USER.139)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000586 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000587BOOL16 WINAPI EmptyClipboard16(void)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000588{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000589 return EmptyClipboard();
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000590}
591
592
593/**************************************************************************
Alexandre Julliard54c27111998-03-29 19:44:57 +0000594 * EmptyClipboard32 (USER32.169)
Noel Borthwick29700671999-09-03 15:17:57 +0000595 * Empties and acquires ownership of the clipboard
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000596 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000597BOOL WINAPI EmptyClipboard(void)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000598{
Noel Borthwick29700671999-09-03 15:17:57 +0000599 TRACE("()\n");
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000600
Noel Borthwick29700671999-09-03 15:17:57 +0000601 if (hClipLock != GetCurrentTask())
602 {
603 WARN("Clipboard not opened by calling task!");
604 return FALSE;
605 }
606
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000607 /* destroy private objects */
608
609 if (hWndClipOwner)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000610 SendMessage16(hWndClipOwner, WM_DESTROYCLIPBOARD, 0, 0L);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000611
Noel Borthwick29700671999-09-03 15:17:57 +0000612 /* empty the cache */
613 CLIPBOARD_EmptyCache(TRUE);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000614
Noel Borthwick29700671999-09-03 15:17:57 +0000615 /* Assign ownership of the clipboard to the current client */
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000616 hWndClipOwner = hWndClipWindow;
617
Noel Borthwick29700671999-09-03 15:17:57 +0000618 /* Save the current task */
619 hTaskClipOwner = GetCurrentTask();
620
621 /* Tell the driver to acquire the selection */
622 CLIPBOARD_Driver->pAcquire();
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000623
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000624 return TRUE;
625}
626
627
628/**************************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000629 * GetClipboardOwner16 (USER.140)
Noel Borthwick29700671999-09-03 15:17:57 +0000630 * FIXME: Can't return the owner if the clipbard is owned by an external app
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000631 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000632HWND16 WINAPI GetClipboardOwner16(void)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000633{
Noel Borthwick29700671999-09-03 15:17:57 +0000634 TRACE("()\n");
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000635 return hWndClipOwner;
636}
637
638
639/**************************************************************************
Alexandre Julliard54c27111998-03-29 19:44:57 +0000640 * GetClipboardOwner32 (USER32.225)
Noel Borthwick29700671999-09-03 15:17:57 +0000641 * FIXME: Can't return the owner if the clipbard is owned by an external app
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000642 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000643HWND WINAPI GetClipboardOwner(void)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000644{
Noel Borthwick29700671999-09-03 15:17:57 +0000645 TRACE("()\n");
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000646 return hWndClipOwner;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000647}
648
649
650/**************************************************************************
Alexandre Julliard21979011997-03-05 08:22:35 +0000651 * SetClipboardData16 (USER.141)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000652 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000653HANDLE16 WINAPI SetClipboardData16( UINT16 wFormat, HANDLE16 hData )
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000654{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000655 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000656
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000657 TRACE("(%04X, %04x) !\n", wFormat, hData);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000658
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000659 /* NOTE: If the hData is zero and current owner doesn't match
660 * the window that opened the clipboard then this application
Noel Borthwick29700671999-09-03 15:17:57 +0000661 * is screwed because WM_RENDERFORMAT will go to the owner.
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000662 * (to become the owner it must call EmptyClipboard() before
663 * adding new data).
664 */
665
Noel Borthwick29700671999-09-03 15:17:57 +0000666 if( CLIPBOARD_IsLocked() || !lpFormat ||
667 (!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) )
668 {
669 WARN("Invalid hData or clipboard not opened by calling task!");
670 return 0;
671 }
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000672
Noel Borthwick29700671999-09-03 15:17:57 +0000673 /* Pass on the request to the driver */
Alex Korobka44a1b591999-04-01 12:03:52 +0000674 CLIPBOARD_Driver->pSetData(wFormat);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000675
Pascal Cuoq724f1901998-10-26 10:58:16 +0000676 if ( lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32 )
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000677 {
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000678 CLIPBOARD_DeleteRecord(lpFormat, TRUE);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000679
680 /* delete existing CF_TEXT/CF_OEMTEXT aliases */
681
Pascal Cuoq724f1901998-10-26 10:58:16 +0000682 if( wFormat == CF_TEXT
683 && ( ClipFormats[CF_OEMTEXT-1].hData16
684 || ClipFormats[CF_OEMTEXT-1].hData32 )
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000685 && !ClipFormats[CF_OEMTEXT-1].wDataPresent )
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000686 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
Pascal Cuoq724f1901998-10-26 10:58:16 +0000687 if( wFormat == CF_OEMTEXT
688 && ( ClipFormats[CF_OEMTEXT-1].hData16
689 || ClipFormats[CF_OEMTEXT-1].hData32 )
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000690 && !ClipFormats[CF_TEXT-1].wDataPresent )
Alexandre Julliarddf2673b1997-03-29 17:20:20 +0000691 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000692 }
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000693
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000694 bCBHasChanged = TRUE;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000695 lpFormat->wDataPresent = 1;
Pascal Cuoq724f1901998-10-26 10:58:16 +0000696 lpFormat->hData16 = hData; /* 0 is legal, see WM_RENDERFORMAT */
697 lpFormat->hData32 = 0;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000698
Pascal Cuoq724f1901998-10-26 10:58:16 +0000699 return lpFormat->hData16;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000700}
701
Alexandre Julliard21979011997-03-05 08:22:35 +0000702
703/**************************************************************************
Alex Korobka44a1b591999-04-01 12:03:52 +0000704 * SetClipboardData (USER32.470)
Alexandre Julliard21979011997-03-05 08:22:35 +0000705 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000706HANDLE WINAPI SetClipboardData( UINT wFormat, HANDLE hData )
Alexandre Julliard21979011997-03-05 08:22:35 +0000707{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000708 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
Pascal Cuoq724f1901998-10-26 10:58:16 +0000709
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000710 TRACE("(%08X, %08x) !\n", wFormat, hData);
Pascal Cuoq724f1901998-10-26 10:58:16 +0000711
712 /* NOTE: If the hData is zero and current owner doesn't match
713 * the window that opened the clipboard then this application
Noel Borthwick29700671999-09-03 15:17:57 +0000714 * is screwed because WM_RENDERFORMAT will go to the owner.
Pascal Cuoq724f1901998-10-26 10:58:16 +0000715 * (to become the owner it must call EmptyClipboard() before
716 * adding new data).
717 */
718
Noel Borthwick29700671999-09-03 15:17:57 +0000719 if( CLIPBOARD_IsLocked() || !lpFormat ||
720 (!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) )
721 {
722 WARN("Invalid hData or clipboard not opened by calling task!");
723 return 0;
724 }
Pascal Cuoq724f1901998-10-26 10:58:16 +0000725
Noel Borthwick29700671999-09-03 15:17:57 +0000726 /* Tell the driver to acquire the selection */
727 CLIPBOARD_Driver->pAcquire();
Pascal Cuoq724f1901998-10-26 10:58:16 +0000728
Noel Borthwick29700671999-09-03 15:17:57 +0000729 if ( lpFormat->wDataPresent &&
730 (lpFormat->hData16 || lpFormat->hData32) )
Pascal Cuoq724f1901998-10-26 10:58:16 +0000731 {
732 CLIPBOARD_DeleteRecord(lpFormat, TRUE);
733
734 /* delete existing CF_TEXT/CF_OEMTEXT aliases */
735
736 if( wFormat == CF_TEXT
737 && ( ClipFormats[CF_OEMTEXT-1].hData16
738 || ClipFormats[CF_OEMTEXT-1].hData32 )
739 && !ClipFormats[CF_OEMTEXT-1].wDataPresent )
740 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
741 if( wFormat == CF_OEMTEXT
742 && ( ClipFormats[CF_OEMTEXT-1].hData16
743 || ClipFormats[CF_OEMTEXT-1].hData32 )
744 && !ClipFormats[CF_TEXT-1].wDataPresent )
745 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
746 }
747
748 bCBHasChanged = TRUE;
749 lpFormat->wDataPresent = 1;
Noel Borthwick83579c81999-07-24 12:18:04 +0000750 lpFormat->hDataSrc32 = hData; /* Save the source handle */
751
752 /*
753 * Make a shared duplicate if the memory is not shared
754 * TODO: What should be done for non-memory objects
755 */
756 if ( CLIPBOARD_IsMemoryObject(wFormat) && hData && !(GlobalFlags(hData) & GMEM_DDESHARE) )
757 lpFormat->hData32 = CLIPBOARD_GlobalDupMem( hData );
758 else
Noel Borthwick29700671999-09-03 15:17:57 +0000759 lpFormat->hData32 = hData; /* 0 is legal, see WM_RENDERFORMAT */
Noel Borthwick83579c81999-07-24 12:18:04 +0000760
Pascal Cuoq724f1901998-10-26 10:58:16 +0000761 lpFormat->hData16 = 0;
762
Noel Borthwick29700671999-09-03 15:17:57 +0000763 return lpFormat->hData32; /* Should we return lpFormat->hDataSrc32 */
Alexandre Julliard21979011997-03-05 08:22:35 +0000764}
765
766
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000767/**************************************************************************
Alexandre Julliard21979011997-03-05 08:22:35 +0000768 * GetClipboardData16 (USER.142)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000769 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000770HANDLE16 WINAPI GetClipboardData16( UINT16 wFormat )
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000771{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000772 LPWINE_CLIPFORMAT lpRender = ClipFormats;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000773
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000774 TRACE("(%04X)\n", wFormat);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000775
Noel Borthwick29700671999-09-03 15:17:57 +0000776 if (CLIPBOARD_IsLocked())
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000777 {
Noel Borthwick29700671999-09-03 15:17:57 +0000778 WARN("Clipboard not opened by calling task!");
779 return 0;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000780 }
Noel Borthwick29700671999-09-03 15:17:57 +0000781
782 if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000783 {
Noel Borthwick29700671999-09-03 15:17:57 +0000784 lpRender = CLIPBOARD_RenderText(wFormat);
785 if ( !lpRender ) return 0;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000786 }
787 else
788 {
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000789 lpRender = __lookup_format( ClipFormats, wFormat );
Noel Borthwick29700671999-09-03 15:17:57 +0000790 if( !lpRender || !CLIPBOARD_RenderFormat(lpRender) ) return 0;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000791 }
792
Noel Borthwick29700671999-09-03 15:17:57 +0000793 /* Convert between 32 -> 16 bit data, if necessary */
Francis Beaudet56ab55d1999-10-24 20:22:24 +0000794 if( lpRender->hData32 && !lpRender->hData16
795 && CLIPBOARD_IsMemoryObject(wFormat) )
Pascal Cuoq724f1901998-10-26 10:58:16 +0000796 {
797 int size;
Noel Borthwick29700671999-09-03 15:17:57 +0000798 if( lpRender->wFormatID == CF_METAFILEPICT )
Pascal Cuoq724f1901998-10-26 10:58:16 +0000799 size = sizeof( METAFILEPICT16 );
800 else
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000801 size = GlobalSize(lpRender->hData32);
802
Noel Borthwick29700671999-09-03 15:17:57 +0000803 lpRender->hData16 = GlobalAlloc16(GMEM_ZEROINIT, size);
804 if( !lpRender->hData16 )
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000805 ERR("(%04X) -- not enough memory in 16b heap\n", wFormat);
Pascal Cuoq724f1901998-10-26 10:58:16 +0000806 else
807 {
Noel Borthwickd05b7be1999-09-20 15:42:47 +0000808 if( lpRender->wFormatID == CF_METAFILEPICT )
809 {
810 FIXME("\timplement function CopyMetaFilePict32to16\n");
811 FIXME("\tin the appropriate file.\n");
812 #ifdef SOMEONE_IMPLEMENTED_ME
813 CopyMetaFilePict32to16( GlobalLock16(lpRender->hData16),
814 GlobalLock(lpRender->hData32) );
815 #endif
816 }
817 else
818 {
819 memcpy( GlobalLock16(lpRender->hData16),
820 GlobalLock(lpRender->hData32),
821 size );
822 }
Noel Borthwick29700671999-09-03 15:17:57 +0000823 GlobalUnlock16(lpRender->hData16);
824 GlobalUnlock(lpRender->hData32);
Pascal Cuoq724f1901998-10-26 10:58:16 +0000825 }
826 }
827
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000828 TRACE("\treturning %04x (type %i)\n",
Noel Borthwick29700671999-09-03 15:17:57 +0000829 lpRender->hData16, lpRender->wFormatID);
830 return lpRender->hData16;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000831}
832
833
834/**************************************************************************
Alexandre Julliard54c27111998-03-29 19:44:57 +0000835 * GetClipboardData32 (USER32.222)
Alexandre Julliard21979011997-03-05 08:22:35 +0000836 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000837HANDLE WINAPI GetClipboardData( UINT wFormat )
Alexandre Julliard21979011997-03-05 08:22:35 +0000838{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000839 LPWINE_CLIPFORMAT lpRender = ClipFormats;
Pascal Cuoq724f1901998-10-26 10:58:16 +0000840
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000841 TRACE("(%08X)\n", wFormat);
Pascal Cuoq724f1901998-10-26 10:58:16 +0000842
Noel Borthwick29700671999-09-03 15:17:57 +0000843 if (CLIPBOARD_IsLocked())
Pascal Cuoq724f1901998-10-26 10:58:16 +0000844 {
Noel Borthwick29700671999-09-03 15:17:57 +0000845 WARN("Clipboard not opened by calling task!");
846 return 0;
Pascal Cuoq724f1901998-10-26 10:58:16 +0000847 }
Noel Borthwick29700671999-09-03 15:17:57 +0000848
849 if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
Pascal Cuoq724f1901998-10-26 10:58:16 +0000850 {
Noel Borthwick29700671999-09-03 15:17:57 +0000851 lpRender = CLIPBOARD_RenderText(wFormat);
852 if ( !lpRender ) return 0;
Pascal Cuoq724f1901998-10-26 10:58:16 +0000853 }
854 else
855 {
856 lpRender = __lookup_format( ClipFormats, wFormat );
Noel Borthwick29700671999-09-03 15:17:57 +0000857 if( !lpRender || !CLIPBOARD_RenderFormat(lpRender) ) return 0;
Pascal Cuoq724f1901998-10-26 10:58:16 +0000858 }
859
Noel Borthwick29700671999-09-03 15:17:57 +0000860 /* Convert between 16 -> 32 bit data, if necessary */
Francis Beaudet56ab55d1999-10-24 20:22:24 +0000861 if( lpRender->hData16 && !lpRender->hData32
862 && CLIPBOARD_IsMemoryObject(wFormat) )
Pascal Cuoq724f1901998-10-26 10:58:16 +0000863 {
864 int size;
Noel Borthwick29700671999-09-03 15:17:57 +0000865 if( lpRender->wFormatID == CF_METAFILEPICT )
Alexandre Julliarda3960291999-02-26 11:11:13 +0000866 size = sizeof( METAFILEPICT );
Pascal Cuoq724f1901998-10-26 10:58:16 +0000867 else
Noel Borthwick29700671999-09-03 15:17:57 +0000868 size = GlobalSize16(lpRender->hData16);
869 lpRender->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE,
Noel Borthwick83579c81999-07-24 12:18:04 +0000870 size);
Noel Borthwick29700671999-09-03 15:17:57 +0000871 if( lpRender->wFormatID == CF_METAFILEPICT )
Pascal Cuoq724f1901998-10-26 10:58:16 +0000872 {
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000873 FIXME("\timplement function CopyMetaFilePict16to32\n");
874 FIXME("\tin the appropriate file.\n");
Pascal Cuoq724f1901998-10-26 10:58:16 +0000875#ifdef SOMEONE_IMPLEMENTED_ME
Noel Borthwick29700671999-09-03 15:17:57 +0000876 CopyMetaFilePict16to32( GlobalLock16(lpRender->hData32),
877 GlobalLock(lpRender->hData16) );
Pascal Cuoq724f1901998-10-26 10:58:16 +0000878#endif
879 }
880 else
881 {
Noel Borthwick29700671999-09-03 15:17:57 +0000882 memcpy( GlobalLock(lpRender->hData32),
883 GlobalLock16(lpRender->hData16),
Pascal Cuoq724f1901998-10-26 10:58:16 +0000884 size );
885 }
Noel Borthwick29700671999-09-03 15:17:57 +0000886 GlobalUnlock(lpRender->hData32);
887 GlobalUnlock16(lpRender->hData16);
Pascal Cuoq724f1901998-10-26 10:58:16 +0000888 }
889
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000890 TRACE("\treturning %04x (type %i)\n",
Noel Borthwick29700671999-09-03 15:17:57 +0000891 lpRender->hData32, lpRender->wFormatID);
892 return lpRender->hData32;
Alexandre Julliard21979011997-03-05 08:22:35 +0000893}
894
Noel Borthwick29700671999-09-03 15:17:57 +0000895
Alexandre Julliard21979011997-03-05 08:22:35 +0000896/**************************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000897 * CountClipboardFormats16 (USER.143)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000898 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000899INT16 WINAPI CountClipboardFormats16(void)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000900{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000901 return CountClipboardFormats();
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000902}
903
904
905/**************************************************************************
Alexandre Julliard54c27111998-03-29 19:44:57 +0000906 * CountClipboardFormats32 (USER32.63)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000907 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000908INT WINAPI CountClipboardFormats(void)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000909{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000910 INT FormatCount = 0;
911 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000912
Noel Borthwick29700671999-09-03 15:17:57 +0000913 TRACE("()\n");
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000914
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000915 while(TRUE)
916 {
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000917 if (lpFormat == NULL) break;
Alex Korobka44a1b591999-04-01 12:03:52 +0000918
Noel Borthwick29700671999-09-03 15:17:57 +0000919 if( lpFormat->wFormatID != CF_TEXT ) /* Don't count CF_TEXT */
920 {
921 /*
922 * The format is available if either:
923 * 1. The data is already in the cache.
924 * 2. The selection is not owned by us(WINE) and the data is
925 * available to the clipboard driver.
926 */
927 if ( lpFormat->wDataPresent ||
928 ( !CLIPBOARD_Driver->pIsSelectionOwner()
929 && CLIPBOARD_Driver->pIsFormatAvailable( lpFormat->wFormatID ) ) )
930 {
931 TRACE("\tdata found for format %i(%s)\n",
932 lpFormat->wFormatID, CLIPBOARD_GetFormatName(lpFormat->wFormatID));
933 FormatCount++;
934 }
935 }
936
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000937 lpFormat = lpFormat->NextFormat;
938 }
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000939
Alex Korobka44a1b591999-04-01 12:03:52 +0000940 /* these two are equivalent, adjust the total */
941
942 FormatCount += abs(ClipFormats[CF_TEXT-1].wDataPresent -
943 ClipFormats[CF_OEMTEXT-1].wDataPresent);
944
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000945 TRACE("\ttotal %d\n", FormatCount);
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000946 return FormatCount;
947}
948
949
950/**************************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000951 * EnumClipboardFormats16 (USER.144)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000952 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000953UINT16 WINAPI EnumClipboardFormats16( UINT16 wFormat )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000954{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000955 return EnumClipboardFormats( wFormat );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000956}
957
958
959/**************************************************************************
Alexandre Julliard54c27111998-03-29 19:44:57 +0000960 * EnumClipboardFormats32 (USER32.179)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000961 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000962UINT WINAPI EnumClipboardFormats( UINT wFormat )
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000963{
Noel Borthwick29700671999-09-03 15:17:57 +0000964 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
965 BOOL bFormatPresent;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000966
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000967 TRACE("(%04X)\n", wFormat);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000968
Noel Borthwick29700671999-09-03 15:17:57 +0000969 if (CLIPBOARD_IsLocked())
970 {
971 WARN("Clipboard not opened by calling task!");
972 return 0;
973 }
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000974
Alex Korobka44a1b591999-04-01 12:03:52 +0000975 if (wFormat == 0) /* start from the beginning */
976 lpFormat = ClipFormats;
977 else
Jesper Skov5c3e4571998-11-01 19:27:22 +0000978 {
Alex Korobka44a1b591999-04-01 12:03:52 +0000979 /* walk up to the specified format record */
980
981 if( !(lpFormat = __lookup_format( lpFormat, wFormat )) )
982 return 0;
983 lpFormat = lpFormat->NextFormat; /* right */
Jesper Skov5c3e4571998-11-01 19:27:22 +0000984 }
Alexandre Julliard1e9ac791996-06-06 18:38:27 +0000985
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000986 while(TRUE)
987 {
Alexandre Julliardfb9a9191994-03-01 19:48:04 +0000988 if (lpFormat == NULL) return 0;
Alex Korobka44a1b591999-04-01 12:03:52 +0000989
Noel Borthwick29700671999-09-03 15:17:57 +0000990 /* Synthesize CF_TEXT from CF_OEMTEXT and vice versa */
991 bFormatPresent = (lpFormat->wDataPresent ||
992 (lpFormat->wFormatID == CF_OEMTEXT && ClipFormats[CF_TEXT-1].wDataPresent) ||
993 (lpFormat->wFormatID == CF_TEXT && ClipFormats[CF_OEMTEXT-1].wDataPresent) );
Alex Korobka44a1b591999-04-01 12:03:52 +0000994
Noel Borthwick29700671999-09-03 15:17:57 +0000995 /* Query the driver if not yet in the cache */
996 if (!bFormatPresent && !CLIPBOARD_Driver->pIsSelectionOwner())
997 {
998 bFormatPresent =
999 CLIPBOARD_Driver->pIsFormatAvailable( (lpFormat->wFormatID == CF_TEXT) ?
1000 CF_OEMTEXT : lpFormat->wFormatID );
1001 }
1002
1003 if (bFormatPresent)
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001004 break;
Noel Borthwick29700671999-09-03 15:17:57 +00001005
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001006 lpFormat = lpFormat->NextFormat;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001007 }
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001008
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001009 return lpFormat->wFormatID;
1010}
1011
1012
1013/**************************************************************************
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001014 * RegisterClipboardFormat16 (USER.145)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001015 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001016UINT16 WINAPI RegisterClipboardFormat16( LPCSTR FormatName )
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001017{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001018 LPWINE_CLIPFORMAT lpNewFormat;
1019 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001020
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001021 if (FormatName == NULL) return 0;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001022
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001023 TRACE("('%s') !\n", FormatName);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001024
1025 /* walk format chain to see if it's already registered */
1026
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001027 while(TRUE)
1028 {
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001029 if ( !strcmp(lpFormat->Name,FormatName) )
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001030 {
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001031 lpFormat->wRefCount++;
1032 return lpFormat->wFormatID;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001033 }
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001034
1035 if ( lpFormat->NextFormat == NULL ) break;
1036
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001037 lpFormat = lpFormat->NextFormat;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001038 }
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001039
1040 /* allocate storage for new format entry */
1041
Alexandre Julliarda3960291999-02-26 11:11:13 +00001042 lpNewFormat = (LPWINE_CLIPFORMAT)xmalloc(sizeof(WINE_CLIPFORMAT));
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001043 lpFormat->NextFormat = lpNewFormat;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001044 lpNewFormat->wFormatID = LastRegFormat;
1045 lpNewFormat->wRefCount = 1;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001046
1047 lpNewFormat->Name = (LPSTR)xmalloc(strlen(FormatName) + 1);
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001048 strcpy(lpNewFormat->Name, FormatName);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001049
1050 lpNewFormat->wDataPresent = 0;
Pascal Cuoq724f1901998-10-26 10:58:16 +00001051 lpNewFormat->hData16 = 0;
Noel Borthwick83579c81999-07-24 12:18:04 +00001052 lpNewFormat->hDataSrc32 = 0;
Pascal Cuoq724f1901998-10-26 10:58:16 +00001053 lpNewFormat->hData32 = 0;
Noel Borthwick29700671999-09-03 15:17:57 +00001054 lpNewFormat->drvData = 0;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001055 lpNewFormat->PrevFormat = lpFormat;
1056 lpNewFormat->NextFormat = NULL;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001057
Noel Borthwick29700671999-09-03 15:17:57 +00001058 /* Pass on the registration request to the driver */
1059 CLIPBOARD_Driver->pRegisterFormat( FormatName );
1060
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001061 return LastRegFormat++;
1062}
1063
1064
1065/**************************************************************************
Alexandre Julliard54c27111998-03-29 19:44:57 +00001066 * RegisterClipboardFormat32A (USER32.431)
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001067 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001068UINT WINAPI RegisterClipboardFormatA( LPCSTR formatName )
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001069{
1070 return RegisterClipboardFormat16( formatName );
1071}
1072
1073
1074/**************************************************************************
Alexandre Julliard54c27111998-03-29 19:44:57 +00001075 * RegisterClipboardFormat32W (USER32.432)
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001076 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001077UINT WINAPI RegisterClipboardFormatW( LPCWSTR formatName )
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001078{
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001079 LPSTR aFormat = HEAP_strdupWtoA( GetProcessHeap(), 0, formatName );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001080 UINT ret = RegisterClipboardFormatA( aFormat );
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001081 HeapFree( GetProcessHeap(), 0, aFormat );
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001082 return ret;
1083}
1084
Noel Borthwick29700671999-09-03 15:17:57 +00001085
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001086/**************************************************************************
Alexandre Julliard21979011997-03-05 08:22:35 +00001087 * GetClipboardFormatName16 (USER.146)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001088 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001089INT16 WINAPI GetClipboardFormatName16( UINT16 wFormat, LPSTR retStr, INT16 maxlen )
Alexandre Julliard21979011997-03-05 08:22:35 +00001090{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001091 return GetClipboardFormatNameA( wFormat, retStr, maxlen );
Alexandre Julliard21979011997-03-05 08:22:35 +00001092}
1093
1094
1095/**************************************************************************
Alexandre Julliard54c27111998-03-29 19:44:57 +00001096 * GetClipboardFormatName32A (USER32.223)
Alexandre Julliard21979011997-03-05 08:22:35 +00001097 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001098INT WINAPI GetClipboardFormatNameA( UINT wFormat, LPSTR retStr, INT maxlen )
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001099{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001100 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001101
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001102 TRACE("(%04X, %p, %d) !\n", wFormat, retStr, maxlen);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001103
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001104 if (lpFormat == NULL || lpFormat->Name == NULL ||
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001105 lpFormat->wFormatID < CF_REGFORMATBASE) return 0;
1106
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001107 TRACE("Name='%s' !\n", lpFormat->Name);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001108
Alexandre Julliarda3960291999-02-26 11:11:13 +00001109 lstrcpynA( retStr, lpFormat->Name, maxlen );
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001110 return strlen(retStr);
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001111}
1112
1113
1114/**************************************************************************
Alexandre Julliard54c27111998-03-29 19:44:57 +00001115 * GetClipboardFormatName32W (USER32.224)
Alexandre Julliard21979011997-03-05 08:22:35 +00001116 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001117INT WINAPI GetClipboardFormatNameW( UINT wFormat, LPWSTR retStr, INT maxlen )
Alexandre Julliard21979011997-03-05 08:22:35 +00001118{
1119 LPSTR p = HEAP_xalloc( GetProcessHeap(), 0, maxlen );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001120 INT ret = GetClipboardFormatNameA( wFormat, p, maxlen );
Alexandre Julliard21979011997-03-05 08:22:35 +00001121 lstrcpynAtoW( retStr, p, maxlen );
1122 HeapFree( GetProcessHeap(), 0, p );
1123 return ret;
1124}
1125
1126
1127/**************************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001128 * SetClipboardViewer16 (USER.147)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001129 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001130HWND16 WINAPI SetClipboardViewer16( HWND16 hWnd )
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001131{
Noel Borthwick29700671999-09-03 15:17:57 +00001132 TRACE("(%04x)\n", hWnd);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001133 return SetClipboardViewer( hWnd );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001134}
1135
1136
1137/**************************************************************************
Alexandre Julliard54c27111998-03-29 19:44:57 +00001138 * SetClipboardViewer32 (USER32.471)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001139 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001140HWND WINAPI SetClipboardViewer( HWND hWnd )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001141{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001142 HWND hwndPrev = hWndViewer;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001143
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001144 TRACE("(%04x): returning %04x\n", hWnd, hwndPrev);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001145
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001146 hWndViewer = hWnd;
Alexandre Julliardecc37121994-11-22 16:31:29 +00001147 return hwndPrev;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001148}
1149
1150
1151/**************************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001152 * GetClipboardViewer16 (USER.148)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001153 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001154HWND16 WINAPI GetClipboardViewer16(void)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001155{
Noel Borthwick29700671999-09-03 15:17:57 +00001156 TRACE("()\n");
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001157 return hWndViewer;
1158}
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001159
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001160
1161/**************************************************************************
Alexandre Julliard54c27111998-03-29 19:44:57 +00001162 * GetClipboardViewer32 (USER32.226)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001163 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001164HWND WINAPI GetClipboardViewer(void)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001165{
Noel Borthwick29700671999-09-03 15:17:57 +00001166 TRACE("()\n");
Alexandre Julliardaca05781994-10-17 18:12:41 +00001167 return hWndViewer;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001168}
1169
1170
1171/**************************************************************************
Alexandre Julliard21979011997-03-05 08:22:35 +00001172 * ChangeClipboardChain16 (USER.149)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001173 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001174BOOL16 WINAPI ChangeClipboardChain16(HWND16 hWnd, HWND16 hWndNext)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001175{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001176 return ChangeClipboardChain(hWnd, hWndNext);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001177}
1178
Noel Borthwick29700671999-09-03 15:17:57 +00001179
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001180/**************************************************************************
Alexandre Julliard54c27111998-03-29 19:44:57 +00001181 * ChangeClipboardChain32 (USER32.22)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001182 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001183BOOL WINAPI ChangeClipboardChain(HWND hWnd, HWND hWndNext)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001184{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001185 BOOL bRet = 0;
Alexandre Julliard234bc241994-12-10 13:02:28 +00001186
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001187 FIXME("(0x%04x, 0x%04x): stub?\n", hWnd, hWndNext);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001188
1189 if( hWndViewer )
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001190 bRet = !SendMessage16( hWndViewer, WM_CHANGECBCHAIN,
Alexandre Julliard530ee841996-10-23 16:59:13 +00001191 (WPARAM16)hWnd, (LPARAM)hWndNext);
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001192 else
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001193 WARN("hWndViewer is lost\n");
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001194
1195 if( hWnd == hWndViewer ) hWndViewer = hWndNext;
1196
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001197 return bRet;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001198}
1199
1200
1201/**************************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001202 * IsClipboardFormatAvailable16 (USER.193)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001203 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001204BOOL16 WINAPI IsClipboardFormatAvailable16( UINT16 wFormat )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001205{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001206 return IsClipboardFormatAvailable( wFormat );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001207}
1208
1209
1210/**************************************************************************
Alexandre Julliard54c27111998-03-29 19:44:57 +00001211 * IsClipboardFormatAvailable32 (USER32.340)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001212 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001213BOOL WINAPI IsClipboardFormatAvailable( UINT wFormat )
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001214{
Noel Borthwick29700671999-09-03 15:17:57 +00001215 BOOL bRet;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001216
Noel Borthwick29700671999-09-03 15:17:57 +00001217 if (wFormat == 0) /* Reject this case quickly */
1218 bRet = FALSE;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001219
Noel Borthwick29700671999-09-03 15:17:57 +00001220 /* If WINE is not the clipboard selection owner ask the clipboard driver */
1221 else if ( !CLIPBOARD_Driver->pIsSelectionOwner() )
1222 bRet = CLIPBOARD_Driver->pIsFormatAvailable( (wFormat == CF_TEXT) ?
1223 CF_OEMTEXT : wFormat );
1224 /* Check if the format is in the local cache */
1225 else
1226 bRet = CLIPBOARD_IsPresent(wFormat);
1227
1228 TRACE("(%04X)- ret(%d)\n", wFormat, bRet);
1229 return bRet;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001230}
1231
1232
1233/**************************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001234 * GetOpenClipboardWindow16 (USER.248)
Noel Borthwick29700671999-09-03 15:17:57 +00001235 * FIXME: This wont work if an external app owns the selection
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001236 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001237HWND16 WINAPI GetOpenClipboardWindow16(void)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001238{
Noel Borthwick29700671999-09-03 15:17:57 +00001239 TRACE("()\n");
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001240 return hWndClipWindow;
1241}
1242
1243
1244/**************************************************************************
Alexandre Julliard54c27111998-03-29 19:44:57 +00001245 * GetOpenClipboardWindow32 (USER32.277)
Noel Borthwick29700671999-09-03 15:17:57 +00001246 * FIXME: This wont work if an external app owns the selection
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001247 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001248HWND WINAPI GetOpenClipboardWindow(void)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001249{
Noel Borthwick29700671999-09-03 15:17:57 +00001250 TRACE("()\n");
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001251 return hWndClipWindow;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001252}
1253
1254
1255/**************************************************************************
Alexandre Julliard21979011997-03-05 08:22:35 +00001256 * GetPriorityClipboardFormat16 (USER.402)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001257 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001258INT16 WINAPI GetPriorityClipboardFormat16( UINT16 *lpPriorityList, INT16 nCount)
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001259{
Alexandre Julliard359f497e1999-07-04 16:02:24 +00001260 FIXME("(%p,%d): stub\n", lpPriorityList, nCount );
Alexandre Julliard21979011997-03-05 08:22:35 +00001261 return 0;
1262}
Alexandre Julliard234bc241994-12-10 13:02:28 +00001263
Alexandre Julliard21979011997-03-05 08:22:35 +00001264
1265/**************************************************************************
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001266 * GetPriorityClipboardFormat32 (USER32.279)
Alexandre Julliard21979011997-03-05 08:22:35 +00001267 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001268INT WINAPI GetPriorityClipboardFormat( UINT *lpPriorityList, INT nCount )
Alexandre Julliard21979011997-03-05 08:22:35 +00001269{
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001270 int Counter;
Noel Borthwick29700671999-09-03 15:17:57 +00001271 TRACE("()\n");
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001272
Alexandre Julliarda3960291999-02-26 11:11:13 +00001273 if(CountClipboardFormats() == 0)
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001274 {
1275 return 0;
1276 }
1277
1278 for(Counter = 0; Counter <= nCount; Counter++)
1279 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001280 if(IsClipboardFormatAvailable(*(lpPriorityList+sizeof(INT)*Counter)))
1281 return *(lpPriorityList+sizeof(INT)*Counter);
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001282 }
1283
1284 return -1;
Alexandre Julliardfb9a9191994-03-01 19:48:04 +00001285}
1286