2 * WIN32 clipboard implementation
4 * Copyright 1994 Martin Ayotte
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)
21 #include <sys/types.h>
27 #include "wine/winuser16.h"
28 #include "wine/winbase16.h"
33 #include "clipboard.h"
35 #include "debugtools.h"
37 DEFAULT_DEBUG_CHANNEL(clipboard
)
39 #define CF_REGFORMATBASE 0xC000
41 /**************************************************************************
42 * Clipboard context global variables
45 CLIPBOARD_DRIVER
*CLIPBOARD_Driver
= NULL
;
47 static HANDLE hClipLock
= 0;
48 static BOOL bCBHasChanged
= FALSE
;
50 HWND hWndClipWindow
= 0; /* window that last opened clipboard */
51 HWND hWndClipOwner
= 0; /* current clipboard owner */
52 HANDLE16 hTaskClipOwner
= 0; /* clipboard owner's task */
53 static HWND hWndViewer
= 0; /* start of viewers chain */
55 static WORD LastRegFormat
= CF_REGFORMATBASE
;
57 /* Clipboard cache initial data.
58 * WARNING: This data ordering is dependendent on the WINE_CLIPFORMAT structure
59 * declared in clipboard.h
61 WINE_CLIPFORMAT ClipFormats
[16] = {
62 { 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
}
81 /**************************************************************************
82 * Internal Clipboard implementation methods
83 **************************************************************************/
86 /**************************************************************************
87 * CLIPBOARD_LookupFormat
89 static LPWINE_CLIPFORMAT
__lookup_format( LPWINE_CLIPFORMAT lpFormat
, WORD wID
)
93 if (lpFormat
== NULL
||
94 lpFormat
->wFormatID
== wID
) break;
95 lpFormat
= lpFormat
->NextFormat
;
100 LPWINE_CLIPFORMAT
CLIPBOARD_LookupFormat( WORD wID
)
102 return __lookup_format( ClipFormats
, wID
);
105 /**************************************************************************
107 * Check if the clipboard cache is available to the caller
109 BOOL
CLIPBOARD_IsLocked()
111 BOOL bIsLocked
= TRUE
;
112 HANDLE16 hTaskCur
= GetCurrentTask();
115 * The clipboard is available:
116 * 1. if the caller's task has opened the clipboard,
118 * 2. if the caller is the clipboard owners task, AND is responding to a
119 * WM_RENDERFORMAT message.
121 if ( hClipLock
== hTaskCur
)
124 else if ( hTaskCur
== hTaskClipOwner
)
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.
132 MESSAGEQUEUE
*queue
= QUEUE_Lock( GetFastQueue16() );
136 && queue
->smWaiting
->msg
== WM_RENDERFORMAT
137 && queue
->smWaiting
->hSrcQueue
141 QUEUE_Unlock( queue
);
147 /**************************************************************************
148 * CLIPBOARD_ReleaseOwner
149 * Gives up ownership of the clipboard
151 void CLIPBOARD_ReleaseOwner()
157 /**************************************************************************
158 * CLIPBOARD_GlobalFreeProc
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
172 VOID CALLBACK
CLIPBOARD_GlobalFreeProc( HWND hwnd
, UINT uMsg
, UINT idEvent
, DWORD dwTime
)
174 /* idEvent is the HGLOBAL to be deleted */
175 GlobalFree( (HGLOBAL
)idEvent
);
178 /**************************************************************************
179 * CLIPBOARD_DeleteRecord
181 void CLIPBOARD_DeleteRecord(LPWINE_CLIPFORMAT lpFormat
, BOOL bChange
)
183 if( (lpFormat
->wFormatID
>= CF_GDIOBJFIRST
&&
184 lpFormat
->wFormatID
<= CF_GDIOBJLAST
) || lpFormat
->wFormatID
== CF_BITMAP
185 || lpFormat
->wFormatID
== CF_PALETTE
)
187 if (lpFormat
->hData32
)
188 DeleteObject(lpFormat
->hData32
);
189 if (lpFormat
->hData16
)
190 DeleteObject16(lpFormat
->hData16
);
192 else if( lpFormat
->wFormatID
== CF_METAFILEPICT
)
194 if (lpFormat
->hData32
)
196 DeleteMetaFile( ((METAFILEPICT
*)GlobalLock( lpFormat
->hData32
))->hMF
);
197 PostMessageA(hWndClipOwner
, WM_TIMER
,
198 (WPARAM
)lpFormat
->hData32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
199 if (lpFormat
->hDataSrc32
)
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);
205 PostMessageA(hWndClipOwner
, WM_TIMER
,
206 (WPARAM
)lpFormat
->hDataSrc32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
209 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
);
216 if (lpFormat
->hData16
)
218 DeleteMetaFile16( ((METAFILEPICT16
*)GlobalLock16( lpFormat
->hData16
))->hMF
);
219 GlobalFree16(lpFormat
->hData16
);
224 if (lpFormat
->hData32
)
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 );
230 PostMessageA(hWndClipOwner
, WM_TIMER
,
231 (WPARAM
)lpFormat
->hData32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
233 if (lpFormat
->hDataSrc32
)
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);
239 PostMessageA(hWndClipOwner
, WM_TIMER
,
240 (WPARAM
)lpFormat
->hDataSrc32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
242 if (lpFormat
->hData16
)
243 GlobalFree16(lpFormat
->hData16
);
246 lpFormat
->wDataPresent
= 0;
247 lpFormat
->hData16
= 0;
248 lpFormat
->hData32
= 0;
249 lpFormat
->hDataSrc32
= 0;
250 lpFormat
->drvData
= 0;
252 if( bChange
) bCBHasChanged
= TRUE
;
255 /**************************************************************************
256 * CLIPBOARD_EmptyCache
258 void CLIPBOARD_EmptyCache( BOOL bChange
)
260 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
264 if ( lpFormat
->wDataPresent
|| lpFormat
->hData16
|| lpFormat
->hData32
)
265 CLIPBOARD_DeleteRecord( lpFormat
, bChange
);
267 lpFormat
= lpFormat
->NextFormat
;
271 /**************************************************************************
272 * CLIPBOARD_IsPresent
274 BOOL
CLIPBOARD_IsPresent(WORD wFormat
)
278 if( wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
)
279 return ClipFormats
[CF_TEXT
-1].wDataPresent
||
280 ClipFormats
[CF_OEMTEXT
-1].wDataPresent
;
283 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
284 if( lpFormat
) return (lpFormat
->wDataPresent
);
289 /**************************************************************************
290 * CLIPBOARD_IsCacheRendered
291 * Checks if any data needs to be rendered to the clipboard cache
293 * TRUE - All clipboard data is available in the cache
294 * FALSE - Some data is marked for delayed render and needs rendering
296 BOOL
CLIPBOARD_IsCacheRendered()
298 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
300 /* check if all formats were rendered */
303 if( lpFormat
->wDataPresent
&& !lpFormat
->hData16
&& !lpFormat
->hData32
)
306 lpFormat
= lpFormat
->NextFormat
;
313 /**************************************************************************
314 * CLIPBOARD_IsMemoryObject
315 * Tests if the clipboard format specifies a memory object
317 BOOL
CLIPBOARD_IsMemoryObject( WORD wFormat
)
322 case CF_METAFILEPICT
:
334 /***********************************************************************
335 * CLIPBOARD_GlobalDupMem( HGLOBAL )
336 * Helper method to duplicate an HGLOBAL chunk of memory into shared memory
338 HGLOBAL
CLIPBOARD_GlobalDupMem( HGLOBAL hGlobalSrc
)
341 PVOID pGlobalSrc
, pGlobalDest
;
347 cBytes
= GlobalSize(hGlobalSrc
);
351 /* Turn on the DDESHARE and _MOVEABLE flags explicitly */
352 hGlobalDest
= GlobalAlloc( GlobalFlags(hGlobalSrc
) | GMEM_DDESHARE
| GMEM_MOVEABLE
,
357 pGlobalSrc
= GlobalLock(hGlobalSrc
);
358 pGlobalDest
= GlobalLock(hGlobalDest
);
359 if ( !pGlobalSrc
|| !pGlobalDest
)
362 memcpy(pGlobalDest
, pGlobalSrc
, cBytes
);
364 GlobalUnlock(hGlobalSrc
);
365 GlobalUnlock(hGlobalDest
);
370 /**************************************************************************
371 * CLIPBOARD_GetFormatName
372 * Gets the format name associated with an ID
374 char * CLIPBOARD_GetFormatName(UINT wFormat
)
376 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
377 return (lpFormat
) ? lpFormat
->Name
: NULL
;
381 /**************************************************************************
382 * CLIPBOARD_RenderFormat
384 static BOOL
CLIPBOARD_RenderFormat(LPWINE_CLIPFORMAT lpFormat
)
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.
390 if ( !CLIPBOARD_Driver
->pIsSelectionOwner()
391 && CLIPBOARD_Driver
->pIsFormatAvailable( lpFormat
->wFormatID
) )
393 if ( !CLIPBOARD_Driver
->pGetData( lpFormat
->wFormatID
) )
397 * If Wine owns the clipboard, and the data is marked for delayed render,
400 else if( lpFormat
->wDataPresent
&& !lpFormat
->hData16
&& !lpFormat
->hData32
)
402 if( IsWindow(hWndClipOwner
) )
404 /* Send a WM_RENDERFORMAT message to notify the owner to render the
405 * data requested into the clipboard.
407 TRACE("Sending WM_RENDERFORMAT message\n");
408 SendMessage16(hWndClipOwner
,WM_RENDERFORMAT
,
409 (WPARAM16
)lpFormat
->wFormatID
,0L);
413 WARN("\thWndClipOwner (%04x) is lost!\n",
415 CLIPBOARD_ReleaseOwner();
416 lpFormat
->wDataPresent
= 0;
421 return (lpFormat
->hData16
|| lpFormat
->hData32
) ? TRUE
: FALSE
;
425 /**************************************************************************
426 * CLIPBOARD_RenderText
428 * Renders text to the clipboard buffer converting between UNIX and DOS formats.
430 * RETURNS: pointer to the WINE_CLIPFORMAT if successful, NULL otherwise
432 * FIXME: Should be a pair of driver functions that convert between OEM text and Windows.
435 static LPWINE_CLIPFORMAT
CLIPBOARD_RenderText( UINT wFormat
)
437 LPWINE_CLIPFORMAT lpSource
= ClipFormats
;
438 LPWINE_CLIPFORMAT lpTarget
;
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
)
443 /* Convert OEMTEXT -> TEXT */
444 lpSource
= &ClipFormats
[CF_OEMTEXT
-1];
445 lpTarget
= &ClipFormats
[CF_TEXT
-1];
447 TRACE("\tOEMTEXT -> TEXT\n");
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
)
453 /* Convert TEXT -> OEMTEXT */
454 lpSource
= &ClipFormats
[CF_TEXT
-1];
455 lpTarget
= &ClipFormats
[CF_OEMTEXT
-1];
457 TRACE("\tTEXT -> OEMTEXT\n");
459 /* Text format requested is available - no conversion necessary */
462 lpSource
= __lookup_format( ClipFormats
, wFormat
);
466 /* First render the source text format */
467 if ( !lpSource
|| !CLIPBOARD_RenderFormat(lpSource
) ) return NULL
;
469 /* Convert to the desired target text format, if necessary */
470 if( lpTarget
!= lpSource
&& !lpTarget
->hData16
&& !lpTarget
->hData32
)
476 if (lpSource
->hData32
)
478 size
= GlobalSize( lpSource
->hData32
);
479 lpstrS
= (LPSTR
)GlobalLock(lpSource
->hData32
);
483 size
= GlobalSize16( lpSource
->hData16
);
484 lpstrS
= (LPSTR
)GlobalLock16(lpSource
->hData16
);
487 if( !lpstrS
) return NULL
;
488 TRACE("\tconverting from '%s' to '%s', %i chars\n",
489 lpSource
->Name
, lpTarget
->Name
, size
);
491 lpTarget
->hData32
= GlobalAlloc(GMEM_ZEROINIT
| GMEM_MOVEABLE
| GMEM_DDESHARE
, size
);
492 lpstrT
= (LPSTR
)GlobalLock(lpTarget
->hData32
);
496 if( lpSource
->wFormatID
== CF_TEXT
)
497 CharToOemBuffA(lpstrS
, lpstrT
, size
);
499 OemToCharBuffA(lpstrS
, lpstrT
, size
);
500 TRACE("\tgot %s\n", lpstrT
);
501 GlobalUnlock(lpTarget
->hData32
);
504 lpTarget
->hData32
= 0;
507 if (lpSource
->hData32
)
508 GlobalUnlock(lpSource
->hData32
);
510 GlobalUnlock16(lpSource
->hData16
);
513 return (lpTarget
->hData16
|| lpTarget
->hData32
) ? lpTarget
: NULL
;
516 /**************************************************************************
517 * WIN32 Clipboard implementation
518 **************************************************************************/
520 /**************************************************************************
521 * OpenClipboard16 (USER.137)
523 BOOL16 WINAPI
OpenClipboard16( HWND16 hWnd
)
525 return OpenClipboard( hWnd
);
529 /**************************************************************************
530 * OpenClipboard32 (USER32.407)
532 * Note: Netscape uses NULL hWnd to open the clipboard.
534 BOOL WINAPI
OpenClipboard( HWND hWnd
)
538 TRACE("(%04x)...\n", hWnd
);
542 hClipLock
= GetCurrentTask();
544 /* Save current user of the clipboard */
545 hWndClipWindow
= hWnd
;
546 bCBHasChanged
= FALSE
;
551 TRACE(" returning %i\n", bRet
);
556 /**************************************************************************
557 * CloseClipboard16 (USER.138)
559 BOOL16 WINAPI
CloseClipboard16(void)
561 return CloseClipboard();
565 /**************************************************************************
566 * CloseClipboard32 (USER32.54)
568 BOOL WINAPI
CloseClipboard(void)
572 if (hClipLock
== GetCurrentTask())
576 if (bCBHasChanged
&& hWndViewer
)
577 SendMessage16(hWndViewer
, WM_DRAWCLIPBOARD
, 0, 0L);
584 /**************************************************************************
585 * EmptyClipboard16 (USER.139)
587 BOOL16 WINAPI
EmptyClipboard16(void)
589 return EmptyClipboard();
593 /**************************************************************************
594 * EmptyClipboard32 (USER32.169)
595 * Empties and acquires ownership of the clipboard
597 BOOL WINAPI
EmptyClipboard(void)
601 if (hClipLock
!= GetCurrentTask())
603 WARN("Clipboard not opened by calling task!");
607 /* destroy private objects */
610 SendMessage16(hWndClipOwner
, WM_DESTROYCLIPBOARD
, 0, 0L);
612 /* empty the cache */
613 CLIPBOARD_EmptyCache(TRUE
);
615 /* Assign ownership of the clipboard to the current client */
616 hWndClipOwner
= hWndClipWindow
;
618 /* Save the current task */
619 hTaskClipOwner
= GetCurrentTask();
621 /* Tell the driver to acquire the selection */
622 CLIPBOARD_Driver
->pAcquire();
628 /**************************************************************************
629 * GetClipboardOwner16 (USER.140)
630 * FIXME: Can't return the owner if the clipbard is owned by an external app
632 HWND16 WINAPI
GetClipboardOwner16(void)
635 return hWndClipOwner
;
639 /**************************************************************************
640 * GetClipboardOwner32 (USER32.225)
641 * FIXME: Can't return the owner if the clipbard is owned by an external app
643 HWND WINAPI
GetClipboardOwner(void)
646 return hWndClipOwner
;
650 /**************************************************************************
651 * SetClipboardData16 (USER.141)
653 HANDLE16 WINAPI
SetClipboardData16( UINT16 wFormat
, HANDLE16 hData
)
655 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
657 TRACE("(%04X, %04x) !\n", wFormat
, hData
);
659 /* NOTE: If the hData is zero and current owner doesn't match
660 * the window that opened the clipboard then this application
661 * is screwed because WM_RENDERFORMAT will go to the owner.
662 * (to become the owner it must call EmptyClipboard() before
666 if( CLIPBOARD_IsLocked() || !lpFormat
||
667 (!hData
&& (!hWndClipOwner
|| (hWndClipOwner
!= hWndClipWindow
))) )
669 WARN("Invalid hData or clipboard not opened by calling task!");
673 /* Pass on the request to the driver */
674 CLIPBOARD_Driver
->pSetData(wFormat
);
676 if ( lpFormat
->wDataPresent
|| lpFormat
->hData16
|| lpFormat
->hData32
)
678 CLIPBOARD_DeleteRecord(lpFormat
, TRUE
);
680 /* delete existing CF_TEXT/CF_OEMTEXT aliases */
682 if( wFormat
== CF_TEXT
683 && ( ClipFormats
[CF_OEMTEXT
-1].hData16
684 || ClipFormats
[CF_OEMTEXT
-1].hData32
)
685 && !ClipFormats
[CF_OEMTEXT
-1].wDataPresent
)
686 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
687 if( wFormat
== CF_OEMTEXT
688 && ( ClipFormats
[CF_OEMTEXT
-1].hData16
689 || ClipFormats
[CF_OEMTEXT
-1].hData32
)
690 && !ClipFormats
[CF_TEXT
-1].wDataPresent
)
691 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
694 bCBHasChanged
= TRUE
;
695 lpFormat
->wDataPresent
= 1;
696 lpFormat
->hData16
= hData
; /* 0 is legal, see WM_RENDERFORMAT */
697 lpFormat
->hData32
= 0;
699 return lpFormat
->hData16
;
703 /**************************************************************************
704 * SetClipboardData (USER32.470)
706 HANDLE WINAPI
SetClipboardData( UINT wFormat
, HANDLE hData
)
708 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
710 TRACE("(%08X, %08x) !\n", wFormat
, hData
);
712 /* NOTE: If the hData is zero and current owner doesn't match
713 * the window that opened the clipboard then this application
714 * is screwed because WM_RENDERFORMAT will go to the owner.
715 * (to become the owner it must call EmptyClipboard() before
719 if( CLIPBOARD_IsLocked() || !lpFormat
||
720 (!hData
&& (!hWndClipOwner
|| (hWndClipOwner
!= hWndClipWindow
))) )
722 WARN("Invalid hData or clipboard not opened by calling task!");
726 /* Tell the driver to acquire the selection */
727 CLIPBOARD_Driver
->pAcquire();
729 if ( lpFormat
->wDataPresent
&&
730 (lpFormat
->hData16
|| lpFormat
->hData32
) )
732 CLIPBOARD_DeleteRecord(lpFormat
, TRUE
);
734 /* delete existing CF_TEXT/CF_OEMTEXT aliases */
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
);
748 bCBHasChanged
= TRUE
;
749 lpFormat
->wDataPresent
= 1;
750 lpFormat
->hDataSrc32
= hData
; /* Save the source handle */
753 * Make a shared duplicate if the memory is not shared
754 * TODO: What should be done for non-memory objects
756 if ( CLIPBOARD_IsMemoryObject(wFormat
) && hData
&& !(GlobalFlags(hData
) & GMEM_DDESHARE
) )
757 lpFormat
->hData32
= CLIPBOARD_GlobalDupMem( hData
);
759 lpFormat
->hData32
= hData
; /* 0 is legal, see WM_RENDERFORMAT */
761 lpFormat
->hData16
= 0;
763 return lpFormat
->hData32
; /* Should we return lpFormat->hDataSrc32 */
767 /**************************************************************************
768 * GetClipboardData16 (USER.142)
770 HANDLE16 WINAPI
GetClipboardData16( UINT16 wFormat
)
772 LPWINE_CLIPFORMAT lpRender
= ClipFormats
;
774 TRACE("(%04X)\n", wFormat
);
776 if (CLIPBOARD_IsLocked())
778 WARN("Clipboard not opened by calling task!");
782 if( wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
)
784 lpRender
= CLIPBOARD_RenderText(wFormat
);
785 if ( !lpRender
) return 0;
789 lpRender
= __lookup_format( ClipFormats
, wFormat
);
790 if( !lpRender
|| !CLIPBOARD_RenderFormat(lpRender
) ) return 0;
793 /* Convert between 32 -> 16 bit data, if necessary */
794 if( lpRender
->hData32
&& !lpRender
->hData16
795 && CLIPBOARD_IsMemoryObject(wFormat
) )
798 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
799 size
= sizeof( METAFILEPICT16
);
801 size
= GlobalSize(lpRender
->hData32
);
803 lpRender
->hData16
= GlobalAlloc16(GMEM_ZEROINIT
, size
);
804 if( !lpRender
->hData16
)
805 ERR("(%04X) -- not enough memory in 16b heap\n", wFormat
);
808 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
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
) );
819 memcpy( GlobalLock16(lpRender
->hData16
),
820 GlobalLock(lpRender
->hData32
),
823 GlobalUnlock16(lpRender
->hData16
);
824 GlobalUnlock(lpRender
->hData32
);
828 TRACE("\treturning %04x (type %i)\n",
829 lpRender
->hData16
, lpRender
->wFormatID
);
830 return lpRender
->hData16
;
834 /**************************************************************************
835 * GetClipboardData32 (USER32.222)
837 HANDLE WINAPI
GetClipboardData( UINT wFormat
)
839 LPWINE_CLIPFORMAT lpRender
= ClipFormats
;
841 TRACE("(%08X)\n", wFormat
);
843 if (CLIPBOARD_IsLocked())
845 WARN("Clipboard not opened by calling task!");
849 if( wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
)
851 lpRender
= CLIPBOARD_RenderText(wFormat
);
852 if ( !lpRender
) return 0;
856 lpRender
= __lookup_format( ClipFormats
, wFormat
);
857 if( !lpRender
|| !CLIPBOARD_RenderFormat(lpRender
) ) return 0;
860 /* Convert between 16 -> 32 bit data, if necessary */
861 if( lpRender
->hData16
&& !lpRender
->hData32
862 && CLIPBOARD_IsMemoryObject(wFormat
) )
865 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
866 size
= sizeof( METAFILEPICT
);
868 size
= GlobalSize16(lpRender
->hData16
);
869 lpRender
->hData32
= GlobalAlloc(GMEM_ZEROINIT
| GMEM_MOVEABLE
| GMEM_DDESHARE
,
871 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
873 FIXME("\timplement function CopyMetaFilePict16to32\n");
874 FIXME("\tin the appropriate file.\n");
875 #ifdef SOMEONE_IMPLEMENTED_ME
876 CopyMetaFilePict16to32( GlobalLock16(lpRender
->hData32
),
877 GlobalLock(lpRender
->hData16
) );
882 memcpy( GlobalLock(lpRender
->hData32
),
883 GlobalLock16(lpRender
->hData16
),
886 GlobalUnlock(lpRender
->hData32
);
887 GlobalUnlock16(lpRender
->hData16
);
890 TRACE("\treturning %04x (type %i)\n",
891 lpRender
->hData32
, lpRender
->wFormatID
);
892 return lpRender
->hData32
;
896 /**************************************************************************
897 * CountClipboardFormats16 (USER.143)
899 INT16 WINAPI
CountClipboardFormats16(void)
901 return CountClipboardFormats();
905 /**************************************************************************
906 * CountClipboardFormats32 (USER32.63)
908 INT WINAPI
CountClipboardFormats(void)
911 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
917 if (lpFormat
== NULL
) break;
919 if( lpFormat
->wFormatID
!= CF_TEXT
) /* Don't count CF_TEXT */
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.
927 if ( lpFormat
->wDataPresent
||
928 ( !CLIPBOARD_Driver
->pIsSelectionOwner()
929 && CLIPBOARD_Driver
->pIsFormatAvailable( lpFormat
->wFormatID
) ) )
931 TRACE("\tdata found for format %i(%s)\n",
932 lpFormat
->wFormatID
, CLIPBOARD_GetFormatName(lpFormat
->wFormatID
));
937 lpFormat
= lpFormat
->NextFormat
;
940 /* these two are equivalent, adjust the total */
942 FormatCount
+= abs(ClipFormats
[CF_TEXT
-1].wDataPresent
-
943 ClipFormats
[CF_OEMTEXT
-1].wDataPresent
);
945 TRACE("\ttotal %d\n", FormatCount
);
950 /**************************************************************************
951 * EnumClipboardFormats16 (USER.144)
953 UINT16 WINAPI
EnumClipboardFormats16( UINT16 wFormat
)
955 return EnumClipboardFormats( wFormat
);
959 /**************************************************************************
960 * EnumClipboardFormats32 (USER32.179)
962 UINT WINAPI
EnumClipboardFormats( UINT wFormat
)
964 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
967 TRACE("(%04X)\n", wFormat
);
969 if (CLIPBOARD_IsLocked())
971 WARN("Clipboard not opened by calling task!");
975 if (wFormat
== 0) /* start from the beginning */
976 lpFormat
= ClipFormats
;
979 /* walk up to the specified format record */
981 if( !(lpFormat
= __lookup_format( lpFormat
, wFormat
)) )
983 lpFormat
= lpFormat
->NextFormat
; /* right */
988 if (lpFormat
== NULL
) return 0;
990 /* 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
) );
995 /* Query the driver if not yet in the cache */
996 if (!bFormatPresent
&& !CLIPBOARD_Driver
->pIsSelectionOwner())
999 CLIPBOARD_Driver
->pIsFormatAvailable( (lpFormat
->wFormatID
== CF_TEXT
) ?
1000 CF_OEMTEXT
: lpFormat
->wFormatID
);
1006 lpFormat
= lpFormat
->NextFormat
;
1009 return lpFormat
->wFormatID
;
1013 /**************************************************************************
1014 * RegisterClipboardFormat16 (USER.145)
1016 UINT16 WINAPI
RegisterClipboardFormat16( LPCSTR FormatName
)
1018 LPWINE_CLIPFORMAT lpNewFormat
;
1019 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
1021 if (FormatName
== NULL
) return 0;
1023 TRACE("('%s') !\n", FormatName
);
1025 /* walk format chain to see if it's already registered */
1029 if ( !strcmp(lpFormat
->Name
,FormatName
) )
1031 lpFormat
->wRefCount
++;
1032 return lpFormat
->wFormatID
;
1035 if ( lpFormat
->NextFormat
== NULL
) break;
1037 lpFormat
= lpFormat
->NextFormat
;
1040 /* allocate storage for new format entry */
1042 lpNewFormat
= (LPWINE_CLIPFORMAT
)xmalloc(sizeof(WINE_CLIPFORMAT
));
1043 lpFormat
->NextFormat
= lpNewFormat
;
1044 lpNewFormat
->wFormatID
= LastRegFormat
;
1045 lpNewFormat
->wRefCount
= 1;
1047 lpNewFormat
->Name
= (LPSTR
)xmalloc(strlen(FormatName
) + 1);
1048 strcpy(lpNewFormat
->Name
, FormatName
);
1050 lpNewFormat
->wDataPresent
= 0;
1051 lpNewFormat
->hData16
= 0;
1052 lpNewFormat
->hDataSrc32
= 0;
1053 lpNewFormat
->hData32
= 0;
1054 lpNewFormat
->drvData
= 0;
1055 lpNewFormat
->PrevFormat
= lpFormat
;
1056 lpNewFormat
->NextFormat
= NULL
;
1058 /* Pass on the registration request to the driver */
1059 CLIPBOARD_Driver
->pRegisterFormat( FormatName
);
1061 return LastRegFormat
++;
1065 /**************************************************************************
1066 * RegisterClipboardFormat32A (USER32.431)
1068 UINT WINAPI
RegisterClipboardFormatA( LPCSTR formatName
)
1070 return RegisterClipboardFormat16( formatName
);
1074 /**************************************************************************
1075 * RegisterClipboardFormat32W (USER32.432)
1077 UINT WINAPI
RegisterClipboardFormatW( LPCWSTR formatName
)
1079 LPSTR aFormat
= HEAP_strdupWtoA( GetProcessHeap(), 0, formatName
);
1080 UINT ret
= RegisterClipboardFormatA( aFormat
);
1081 HeapFree( GetProcessHeap(), 0, aFormat
);
1086 /**************************************************************************
1087 * GetClipboardFormatName16 (USER.146)
1089 INT16 WINAPI
GetClipboardFormatName16( UINT16 wFormat
, LPSTR retStr
, INT16 maxlen
)
1091 return GetClipboardFormatNameA( wFormat
, retStr
, maxlen
);
1095 /**************************************************************************
1096 * GetClipboardFormatName32A (USER32.223)
1098 INT WINAPI
GetClipboardFormatNameA( UINT wFormat
, LPSTR retStr
, INT maxlen
)
1100 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
1102 TRACE("(%04X, %p, %d) !\n", wFormat
, retStr
, maxlen
);
1104 if (lpFormat
== NULL
|| lpFormat
->Name
== NULL
||
1105 lpFormat
->wFormatID
< CF_REGFORMATBASE
) return 0;
1107 TRACE("Name='%s' !\n", lpFormat
->Name
);
1109 lstrcpynA( retStr
, lpFormat
->Name
, maxlen
);
1110 return strlen(retStr
);
1114 /**************************************************************************
1115 * GetClipboardFormatName32W (USER32.224)
1117 INT WINAPI
GetClipboardFormatNameW( UINT wFormat
, LPWSTR retStr
, INT maxlen
)
1119 LPSTR p
= HEAP_xalloc( GetProcessHeap(), 0, maxlen
);
1120 INT ret
= GetClipboardFormatNameA( wFormat
, p
, maxlen
);
1121 lstrcpynAtoW( retStr
, p
, maxlen
);
1122 HeapFree( GetProcessHeap(), 0, p
);
1127 /**************************************************************************
1128 * SetClipboardViewer16 (USER.147)
1130 HWND16 WINAPI
SetClipboardViewer16( HWND16 hWnd
)
1132 TRACE("(%04x)\n", hWnd
);
1133 return SetClipboardViewer( hWnd
);
1137 /**************************************************************************
1138 * SetClipboardViewer32 (USER32.471)
1140 HWND WINAPI
SetClipboardViewer( HWND hWnd
)
1142 HWND hwndPrev
= hWndViewer
;
1144 TRACE("(%04x): returning %04x\n", hWnd
, hwndPrev
);
1151 /**************************************************************************
1152 * GetClipboardViewer16 (USER.148)
1154 HWND16 WINAPI
GetClipboardViewer16(void)
1161 /**************************************************************************
1162 * GetClipboardViewer32 (USER32.226)
1164 HWND WINAPI
GetClipboardViewer(void)
1171 /**************************************************************************
1172 * ChangeClipboardChain16 (USER.149)
1174 BOOL16 WINAPI
ChangeClipboardChain16(HWND16 hWnd
, HWND16 hWndNext
)
1176 return ChangeClipboardChain(hWnd
, hWndNext
);
1180 /**************************************************************************
1181 * ChangeClipboardChain32 (USER32.22)
1183 BOOL WINAPI
ChangeClipboardChain(HWND hWnd
, HWND hWndNext
)
1187 FIXME("(0x%04x, 0x%04x): stub?\n", hWnd
, hWndNext
);
1190 bRet
= !SendMessage16( hWndViewer
, WM_CHANGECBCHAIN
,
1191 (WPARAM16
)hWnd
, (LPARAM
)hWndNext
);
1193 WARN("hWndViewer is lost\n");
1195 if( hWnd
== hWndViewer
) hWndViewer
= hWndNext
;
1201 /**************************************************************************
1202 * IsClipboardFormatAvailable16 (USER.193)
1204 BOOL16 WINAPI
IsClipboardFormatAvailable16( UINT16 wFormat
)
1206 return IsClipboardFormatAvailable( wFormat
);
1210 /**************************************************************************
1211 * IsClipboardFormatAvailable32 (USER32.340)
1213 BOOL WINAPI
IsClipboardFormatAvailable( UINT wFormat
)
1217 if (wFormat
== 0) /* Reject this case quickly */
1220 /* 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 */
1226 bRet
= CLIPBOARD_IsPresent(wFormat
);
1228 TRACE("(%04X)- ret(%d)\n", wFormat
, bRet
);
1233 /**************************************************************************
1234 * GetOpenClipboardWindow16 (USER.248)
1235 * FIXME: This wont work if an external app owns the selection
1237 HWND16 WINAPI
GetOpenClipboardWindow16(void)
1240 return hWndClipWindow
;
1244 /**************************************************************************
1245 * GetOpenClipboardWindow32 (USER32.277)
1246 * FIXME: This wont work if an external app owns the selection
1248 HWND WINAPI
GetOpenClipboardWindow(void)
1251 return hWndClipWindow
;
1255 /**************************************************************************
1256 * GetPriorityClipboardFormat16 (USER.402)
1258 INT16 WINAPI
GetPriorityClipboardFormat16( UINT16
*lpPriorityList
, INT16 nCount
)
1260 FIXME("(%p,%d): stub\n", lpPriorityList
, nCount
);
1265 /**************************************************************************
1266 * GetPriorityClipboardFormat32 (USER32.279)
1268 INT WINAPI
GetPriorityClipboardFormat( UINT
*lpPriorityList
, INT nCount
)
1273 if(CountClipboardFormats() == 0)
1278 for(Counter
= 0; Counter
<= nCount
; Counter
++)
1280 if(IsClipboardFormatAvailable(*(lpPriorityList
+sizeof(INT
)*Counter
)))
1281 return *(lpPriorityList
+sizeof(INT
)*Counter
);