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>
29 #include "wine/winuser16.h"
30 #include "wine/winbase16.h"
35 #include "clipboard.h"
37 #include "debugtools.h"
39 DEFAULT_DEBUG_CHANNEL(clipboard
)
41 #define CF_REGFORMATBASE 0xC000
43 /**************************************************************************
44 * Clipboard context global variables
47 CLIPBOARD_DRIVER
*CLIPBOARD_Driver
= NULL
;
49 static HANDLE hClipLock
= 0;
50 static BOOL bCBHasChanged
= FALSE
;
52 HWND hWndClipWindow
= 0; /* window that last opened clipboard */
53 HWND hWndClipOwner
= 0; /* current clipboard owner */
54 HANDLE16 hTaskClipOwner
= 0; /* clipboard owner's task */
55 static HWND hWndViewer
= 0; /* start of viewers chain */
57 static WORD LastRegFormat
= CF_REGFORMATBASE
;
59 /* Clipboard cache initial data.
60 * WARNING: This data ordering is dependendent on the WINE_CLIPFORMAT structure
61 * declared in clipboard.h
63 WINE_CLIPFORMAT ClipFormats
[17] = {
64 { CF_TEXT
, 1, 0, "Text", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, NULL
, &ClipFormats
[1]},
65 { CF_BITMAP
, 1, 0, "Bitmap", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, &ClipFormats
[0], &ClipFormats
[2]},
66 { CF_METAFILEPICT
, 1, 0, "MetaFile Picture", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, &ClipFormats
[1], &ClipFormats
[3]},
67 { CF_SYLK
, 1, 0, "Sylk", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, &ClipFormats
[2], &ClipFormats
[4]},
68 { CF_DIF
, 1, 0, "DIF", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, &ClipFormats
[3], &ClipFormats
[5]},
69 { CF_TIFF
, 1, 0, "TIFF", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, &ClipFormats
[4], &ClipFormats
[6]},
70 { CF_OEMTEXT
, 1, 0, "OEM Text", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, &ClipFormats
[5], &ClipFormats
[7]},
71 { CF_DIB
, 1, 0, "DIB", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, &ClipFormats
[6], &ClipFormats
[8]},
72 { CF_PALETTE
, 1, 0, "Palette", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, &ClipFormats
[7], &ClipFormats
[9]},
73 { CF_PENDATA
, 1, 0, "PenData", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, &ClipFormats
[8], &ClipFormats
[10]},
74 { CF_RIFF
, 1, 0, "RIFF", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, &ClipFormats
[9], &ClipFormats
[11]},
75 { CF_WAVE
, 1, 0, "Wave", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, &ClipFormats
[10], &ClipFormats
[12]},
76 { CF_OWNERDISPLAY
, 1, 0, "Owner Display", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, &ClipFormats
[11], &ClipFormats
[13]},
77 { CF_DSPTEXT
, 1, 0, "DSPText", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, &ClipFormats
[12], &ClipFormats
[14]},
78 { CF_DSPMETAFILEPICT
, 1, 0, "DSPMetaFile Picture", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, &ClipFormats
[13], &ClipFormats
[15]},
79 { CF_DSPBITMAP
, 1, 0, "DSPBitmap", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, &ClipFormats
[14], &ClipFormats
[16]},
80 { CF_HDROP
, 1, 0, "HDROP", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, &ClipFormats
[15], NULL
}
84 /**************************************************************************
85 * Internal Clipboard implementation methods
86 **************************************************************************/
89 /**************************************************************************
90 * CLIPBOARD_LookupFormat
92 static LPWINE_CLIPFORMAT
__lookup_format( LPWINE_CLIPFORMAT lpFormat
, WORD wID
)
96 if (lpFormat
== NULL
||
97 lpFormat
->wFormatID
== wID
) break;
98 lpFormat
= lpFormat
->NextFormat
;
103 LPWINE_CLIPFORMAT
CLIPBOARD_LookupFormat( WORD wID
)
105 return __lookup_format( ClipFormats
, wID
);
108 /**************************************************************************
110 * Check if the clipboard cache is available to the caller
112 BOOL
CLIPBOARD_IsLocked()
114 BOOL bIsLocked
= TRUE
;
115 HANDLE16 hTaskCur
= GetCurrentTask();
118 * The clipboard is available:
119 * 1. if the caller's task has opened the clipboard,
121 * 2. if the caller is the clipboard owners task, AND is responding to a
122 * WM_RENDERFORMAT message.
124 if ( hClipLock
== hTaskCur
)
127 else if ( hTaskCur
== hTaskClipOwner
)
129 /* Check if we're currently executing inside a window procedure
130 * called in response to a WM_RENDERFORMAT message. A WM_RENDERFORMAT
131 * handler is not permitted to open the clipboard since it has been opened
132 * by another client. However the handler must have access to the
133 * clipboard in order to update data in response to this message.
135 MESSAGEQUEUE
*queue
= QUEUE_Lock( GetFastQueue16() );
139 && queue
->smWaiting
->msg
== WM_RENDERFORMAT
140 && queue
->smWaiting
->hSrcQueue
144 QUEUE_Unlock( queue
);
150 /**************************************************************************
151 * CLIPBOARD_ReleaseOwner
152 * Gives up ownership of the clipboard
154 void CLIPBOARD_ReleaseOwner()
160 /**************************************************************************
161 * CLIPBOARD_GlobalFreeProc
163 * This is a callback mechanism to allow HGLOBAL data to be released in
164 * the context of the process which allocated it. We post a WM_TIMER message
165 * to the owner window(in CLIPBOARD_DeleteRecord) and destroy the data(in idEvent)
166 * in this WndProc, which is invoked when the apps message loop calls DispatchMessage.
167 * This technique is discussed in Matt Pietrek's "Under the Hood".
168 * An article describing the same may be found in MSDN by searching for WM_TIMER.
169 * Note that this mechanism will probably stop working when WINE supports
170 * address space separation. When "queue events" are implemented in Wine we
171 * should switch to using that mechanism, since it is more robust and does not
172 * require a procedure address to be passed. See the SetWinEventHook API for
175 VOID CALLBACK
CLIPBOARD_GlobalFreeProc( HWND hwnd
, UINT uMsg
, UINT idEvent
, DWORD dwTime
)
177 /* idEvent is the HGLOBAL to be deleted */
178 GlobalFree( (HGLOBAL
)idEvent
);
181 /**************************************************************************
182 * CLIPBOARD_DeleteRecord
184 void CLIPBOARD_DeleteRecord(LPWINE_CLIPFORMAT lpFormat
, BOOL bChange
)
186 if( (lpFormat
->wFormatID
>= CF_GDIOBJFIRST
&&
187 lpFormat
->wFormatID
<= CF_GDIOBJLAST
) || lpFormat
->wFormatID
== CF_BITMAP
188 || lpFormat
->wFormatID
== CF_PALETTE
)
190 if (lpFormat
->hData32
)
191 DeleteObject(lpFormat
->hData32
);
192 if (lpFormat
->hData16
)
193 DeleteObject16(lpFormat
->hData16
);
195 else if( lpFormat
->wFormatID
== CF_METAFILEPICT
)
197 if (lpFormat
->hData32
)
199 DeleteMetaFile( ((METAFILEPICT
*)GlobalLock( lpFormat
->hData32
))->hMF
);
200 PostMessageA(hWndClipOwner
, WM_TIMER
,
201 (WPARAM
)lpFormat
->hData32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
202 if (lpFormat
->hDataSrc32
)
204 /* Release lpFormat->hData32 in the context of the process which created it.
205 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
206 * GlobalFree(lpFormat->hDataSrc32);
208 PostMessageA(hWndClipOwner
, WM_TIMER
,
209 (WPARAM
)lpFormat
->hDataSrc32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
212 if (lpFormat
->hData16
)
213 /* HMETAFILE16 and HMETAFILE32 are apparently the same thing,
214 and a shallow copy is enough to share a METAFILEPICT
215 structure between 16bit and 32bit clipboards. The MetaFile
216 should of course only be deleted once. */
217 GlobalFree16(lpFormat
->hData16
);
219 if (lpFormat
->hData16
)
221 DeleteMetaFile16( ((METAFILEPICT16
*)GlobalLock16( lpFormat
->hData16
))->hMF
);
222 GlobalFree16(lpFormat
->hData16
);
227 if (lpFormat
->hData32
)
229 /* Release lpFormat->hData32 in the context of the process which created it.
230 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
231 * GlobalFree( lpFormat->hData32 );
233 PostMessageA(hWndClipOwner
, WM_TIMER
,
234 (WPARAM
)lpFormat
->hData32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
236 if (lpFormat
->hDataSrc32
)
238 /* Release lpFormat->hData32 in the context of the process which created it.
239 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
240 * GlobalFree(lpFormat->hDataSrc32);
242 PostMessageA(hWndClipOwner
, WM_TIMER
,
243 (WPARAM
)lpFormat
->hDataSrc32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
245 if (lpFormat
->hData16
)
246 GlobalFree16(lpFormat
->hData16
);
249 lpFormat
->wDataPresent
= 0;
250 lpFormat
->hData16
= 0;
251 lpFormat
->hData32
= 0;
252 lpFormat
->hDataSrc32
= 0;
253 lpFormat
->drvData
= 0;
255 if( bChange
) bCBHasChanged
= TRUE
;
258 /**************************************************************************
259 * CLIPBOARD_EmptyCache
261 void CLIPBOARD_EmptyCache( BOOL bChange
)
263 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
267 if ( lpFormat
->wDataPresent
|| lpFormat
->hData16
|| lpFormat
->hData32
)
268 CLIPBOARD_DeleteRecord( lpFormat
, bChange
);
270 lpFormat
= lpFormat
->NextFormat
;
274 /**************************************************************************
275 * CLIPBOARD_IsPresent
277 BOOL
CLIPBOARD_IsPresent(WORD wFormat
)
281 if( wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
)
282 return ClipFormats
[CF_TEXT
-1].wDataPresent
||
283 ClipFormats
[CF_OEMTEXT
-1].wDataPresent
;
286 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
287 if( lpFormat
) return (lpFormat
->wDataPresent
);
292 /**************************************************************************
293 * CLIPBOARD_IsCacheRendered
294 * Checks if any data needs to be rendered to the clipboard cache
296 * TRUE - All clipboard data is available in the cache
297 * FALSE - Some data is marked for delayed render and needs rendering
299 BOOL
CLIPBOARD_IsCacheRendered()
301 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
303 /* check if all formats were rendered */
306 if( lpFormat
->wDataPresent
&& !lpFormat
->hData16
&& !lpFormat
->hData32
)
309 lpFormat
= lpFormat
->NextFormat
;
316 /**************************************************************************
317 * CLIPBOARD_IsMemoryObject
318 * Tests if the clipboard format specifies a memory object
320 BOOL
CLIPBOARD_IsMemoryObject( WORD wFormat
)
325 case CF_METAFILEPICT
:
337 /***********************************************************************
338 * CLIPBOARD_GlobalDupMem( HGLOBAL )
339 * Helper method to duplicate an HGLOBAL chunk of memory into shared memory
341 HGLOBAL
CLIPBOARD_GlobalDupMem( HGLOBAL hGlobalSrc
)
344 PVOID pGlobalSrc
, pGlobalDest
;
350 cBytes
= GlobalSize(hGlobalSrc
);
354 /* Turn on the DDESHARE and _MOVEABLE flags explicitly */
355 hGlobalDest
= GlobalAlloc( GlobalFlags(hGlobalSrc
) | GMEM_DDESHARE
| GMEM_MOVEABLE
,
360 pGlobalSrc
= GlobalLock(hGlobalSrc
);
361 pGlobalDest
= GlobalLock(hGlobalDest
);
362 if ( !pGlobalSrc
|| !pGlobalDest
)
365 memcpy(pGlobalDest
, pGlobalSrc
, cBytes
);
367 GlobalUnlock(hGlobalSrc
);
368 GlobalUnlock(hGlobalDest
);
373 /**************************************************************************
374 * CLIPBOARD_GetFormatName
375 * Gets the format name associated with an ID
377 char * CLIPBOARD_GetFormatName(UINT wFormat
)
379 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
380 return (lpFormat
) ? lpFormat
->Name
: NULL
;
384 /**************************************************************************
385 * CLIPBOARD_RenderFormat
387 static BOOL
CLIPBOARD_RenderFormat(LPWINE_CLIPFORMAT lpFormat
)
390 * If WINE is not the selection owner, and the format is available
391 * we must ask the the driver to render the data to the clipboard cache.
393 if ( !CLIPBOARD_Driver
->pIsSelectionOwner()
394 && CLIPBOARD_Driver
->pIsFormatAvailable( lpFormat
->wFormatID
) )
396 if ( !CLIPBOARD_Driver
->pGetData( lpFormat
->wFormatID
) )
400 * If Wine owns the clipboard, and the data is marked for delayed render,
403 else if( lpFormat
->wDataPresent
&& !lpFormat
->hData16
&& !lpFormat
->hData32
)
405 if( IsWindow(hWndClipOwner
) )
407 /* Send a WM_RENDERFORMAT message to notify the owner to render the
408 * data requested into the clipboard.
410 TRACE("Sending WM_RENDERFORMAT message\n");
411 SendMessage16(hWndClipOwner
,WM_RENDERFORMAT
,
412 (WPARAM16
)lpFormat
->wFormatID
,0L);
416 WARN("\thWndClipOwner (%04x) is lost!\n",
418 CLIPBOARD_ReleaseOwner();
419 lpFormat
->wDataPresent
= 0;
424 return (lpFormat
->hData16
|| lpFormat
->hData32
) ? TRUE
: FALSE
;
428 /**************************************************************************
429 * CLIPBOARD_RenderText
431 * Renders text to the clipboard buffer converting between UNIX and DOS formats.
433 * RETURNS: pointer to the WINE_CLIPFORMAT if successful, NULL otherwise
435 * FIXME: Should be a pair of driver functions that convert between OEM text and Windows.
438 static LPWINE_CLIPFORMAT
CLIPBOARD_RenderText( UINT wFormat
)
440 LPWINE_CLIPFORMAT lpSource
= ClipFormats
;
441 LPWINE_CLIPFORMAT lpTarget
;
443 /* Asked for CF_TEXT and not available - always attempt to convert from CF_OEM_TEXT */
444 if( wFormat
== CF_TEXT
&& !ClipFormats
[CF_TEXT
-1].wDataPresent
)
446 /* Convert OEMTEXT -> TEXT */
447 lpSource
= &ClipFormats
[CF_OEMTEXT
-1];
448 lpTarget
= &ClipFormats
[CF_TEXT
-1];
450 TRACE("\tOEMTEXT -> TEXT\n");
452 /* Asked for CF_OEM_TEXT, and CF_TEXT available */
453 else if( wFormat
== CF_OEMTEXT
&& !ClipFormats
[CF_OEMTEXT
-1].wDataPresent
454 && ClipFormats
[CF_TEXT
-1].wDataPresent
)
456 /* Convert TEXT -> OEMTEXT */
457 lpSource
= &ClipFormats
[CF_TEXT
-1];
458 lpTarget
= &ClipFormats
[CF_OEMTEXT
-1];
460 TRACE("\tTEXT -> OEMTEXT\n");
462 /* Text format requested is available - no conversion necessary */
465 lpSource
= __lookup_format( ClipFormats
, wFormat
);
469 /* First render the source text format */
470 if ( !lpSource
|| !CLIPBOARD_RenderFormat(lpSource
) ) return NULL
;
472 /* Convert to the desired target text format, if necessary */
473 if( lpTarget
!= lpSource
&& !lpTarget
->hData16
&& !lpTarget
->hData32
)
479 if (lpSource
->hData32
)
481 size
= GlobalSize( lpSource
->hData32
);
482 lpstrS
= (LPSTR
)GlobalLock(lpSource
->hData32
);
486 size
= GlobalSize16( lpSource
->hData16
);
487 lpstrS
= (LPSTR
)GlobalLock16(lpSource
->hData16
);
490 if( !lpstrS
) return NULL
;
491 TRACE("\tconverting from '%s' to '%s', %i chars\n",
492 lpSource
->Name
, lpTarget
->Name
, size
);
494 lpTarget
->hData32
= GlobalAlloc(GMEM_ZEROINIT
| GMEM_MOVEABLE
| GMEM_DDESHARE
, size
);
495 lpstrT
= (LPSTR
)GlobalLock(lpTarget
->hData32
);
499 if( lpSource
->wFormatID
== CF_TEXT
)
500 CharToOemBuffA(lpstrS
, lpstrT
, size
);
502 OemToCharBuffA(lpstrS
, lpstrT
, size
);
503 TRACE("\tgot %s\n", lpstrT
);
504 GlobalUnlock(lpTarget
->hData32
);
507 lpTarget
->hData32
= 0;
510 if (lpSource
->hData32
)
511 GlobalUnlock(lpSource
->hData32
);
513 GlobalUnlock16(lpSource
->hData16
);
516 return (lpTarget
->hData16
|| lpTarget
->hData32
) ? lpTarget
: NULL
;
519 /**************************************************************************
520 * WIN32 Clipboard implementation
521 **************************************************************************/
523 /**************************************************************************
524 * OpenClipboard16 (USER.137)
526 BOOL16 WINAPI
OpenClipboard16( HWND16 hWnd
)
528 return OpenClipboard( hWnd
);
532 /**************************************************************************
533 * OpenClipboard32 (USER32.407)
535 * Note: Netscape uses NULL hWnd to open the clipboard.
537 BOOL WINAPI
OpenClipboard( HWND hWnd
)
541 TRACE("(%04x)...\n", hWnd
);
545 hClipLock
= GetCurrentTask();
547 /* Save current user of the clipboard */
548 hWndClipWindow
= hWnd
;
549 bCBHasChanged
= FALSE
;
554 TRACE(" returning %i\n", bRet
);
559 /**************************************************************************
560 * CloseClipboard16 (USER.138)
562 BOOL16 WINAPI
CloseClipboard16(void)
564 return CloseClipboard();
568 /**************************************************************************
569 * CloseClipboard32 (USER32.54)
571 BOOL WINAPI
CloseClipboard(void)
575 if (hClipLock
== GetCurrentTask())
579 if (bCBHasChanged
&& hWndViewer
)
580 SendMessage16(hWndViewer
, WM_DRAWCLIPBOARD
, 0, 0L);
587 /**************************************************************************
588 * EmptyClipboard16 (USER.139)
590 BOOL16 WINAPI
EmptyClipboard16(void)
592 return EmptyClipboard();
596 /**************************************************************************
597 * EmptyClipboard32 (USER32.169)
598 * Empties and acquires ownership of the clipboard
600 BOOL WINAPI
EmptyClipboard(void)
604 if (hClipLock
!= GetCurrentTask())
606 WARN("Clipboard not opened by calling task!");
610 /* destroy private objects */
613 SendMessage16(hWndClipOwner
, WM_DESTROYCLIPBOARD
, 0, 0L);
615 /* empty the cache */
616 CLIPBOARD_EmptyCache(TRUE
);
618 /* Assign ownership of the clipboard to the current client */
619 hWndClipOwner
= hWndClipWindow
;
621 /* Save the current task */
622 hTaskClipOwner
= GetCurrentTask();
624 /* Tell the driver to acquire the selection */
625 CLIPBOARD_Driver
->pAcquire();
631 /**************************************************************************
632 * GetClipboardOwner16 (USER.140)
633 * FIXME: Can't return the owner if the clipbard is owned by an external app
635 HWND16 WINAPI
GetClipboardOwner16(void)
638 return hWndClipOwner
;
642 /**************************************************************************
643 * GetClipboardOwner32 (USER32.225)
644 * FIXME: Can't return the owner if the clipbard is owned by an external app
646 HWND WINAPI
GetClipboardOwner(void)
649 return hWndClipOwner
;
653 /**************************************************************************
654 * SetClipboardData16 (USER.141)
656 HANDLE16 WINAPI
SetClipboardData16( UINT16 wFormat
, HANDLE16 hData
)
658 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
660 TRACE("(%04X, %04x) !\n", wFormat
, hData
);
662 /* NOTE: If the hData is zero and current owner doesn't match
663 * the window that opened the clipboard then this application
664 * is screwed because WM_RENDERFORMAT will go to the owner.
665 * (to become the owner it must call EmptyClipboard() before
669 if( CLIPBOARD_IsLocked() || !lpFormat
||
670 (!hData
&& (!hWndClipOwner
|| (hWndClipOwner
!= hWndClipWindow
))) )
672 WARN("Invalid hData or clipboard not opened by calling task!\n");
676 /* Pass on the request to the driver */
677 CLIPBOARD_Driver
->pSetData(wFormat
);
679 if ( lpFormat
->wDataPresent
|| lpFormat
->hData16
|| lpFormat
->hData32
)
681 CLIPBOARD_DeleteRecord(lpFormat
, TRUE
);
683 /* delete existing CF_TEXT/CF_OEMTEXT aliases */
685 if( wFormat
== CF_TEXT
686 && ( ClipFormats
[CF_OEMTEXT
-1].hData16
687 || ClipFormats
[CF_OEMTEXT
-1].hData32
)
688 && !ClipFormats
[CF_OEMTEXT
-1].wDataPresent
)
689 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
690 if( wFormat
== CF_OEMTEXT
691 && ( ClipFormats
[CF_OEMTEXT
-1].hData16
692 || ClipFormats
[CF_OEMTEXT
-1].hData32
)
693 && !ClipFormats
[CF_TEXT
-1].wDataPresent
)
694 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
697 bCBHasChanged
= TRUE
;
698 lpFormat
->wDataPresent
= 1;
699 lpFormat
->hData16
= hData
; /* 0 is legal, see WM_RENDERFORMAT */
700 lpFormat
->hData32
= 0;
702 return lpFormat
->hData16
;
706 /**************************************************************************
707 * SetClipboardData (USER32.470)
709 HANDLE WINAPI
SetClipboardData( UINT wFormat
, HANDLE hData
)
711 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
713 TRACE("(%08X, %08x) !\n", wFormat
, hData
);
715 /* NOTE: If the hData is zero and current owner doesn't match
716 * the window that opened the clipboard then this application
717 * is screwed because WM_RENDERFORMAT will go to the owner.
718 * (to become the owner it must call EmptyClipboard() before
722 if( CLIPBOARD_IsLocked() || !lpFormat
||
723 (!hData
&& (!hWndClipOwner
|| (hWndClipOwner
!= hWndClipWindow
))) )
725 WARN("Invalid hData or clipboard not opened by calling task!\n");
729 /* Tell the driver to acquire the selection */
730 CLIPBOARD_Driver
->pAcquire();
732 if ( lpFormat
->wDataPresent
&&
733 (lpFormat
->hData16
|| lpFormat
->hData32
) )
735 CLIPBOARD_DeleteRecord(lpFormat
, TRUE
);
737 /* delete existing CF_TEXT/CF_OEMTEXT aliases */
739 if( wFormat
== CF_TEXT
740 && ( ClipFormats
[CF_OEMTEXT
-1].hData16
741 || ClipFormats
[CF_OEMTEXT
-1].hData32
)
742 && !ClipFormats
[CF_OEMTEXT
-1].wDataPresent
)
743 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
744 if( wFormat
== CF_OEMTEXT
745 && ( ClipFormats
[CF_OEMTEXT
-1].hData16
746 || ClipFormats
[CF_OEMTEXT
-1].hData32
)
747 && !ClipFormats
[CF_TEXT
-1].wDataPresent
)
748 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
751 bCBHasChanged
= TRUE
;
752 lpFormat
->wDataPresent
= 1;
753 lpFormat
->hDataSrc32
= hData
; /* Save the source handle */
756 * Make a shared duplicate if the memory is not shared
757 * TODO: What should be done for non-memory objects
759 if ( CLIPBOARD_IsMemoryObject(wFormat
) && hData
&& !(GlobalFlags(hData
) & GMEM_DDESHARE
) )
760 lpFormat
->hData32
= CLIPBOARD_GlobalDupMem( hData
);
762 lpFormat
->hData32
= hData
; /* 0 is legal, see WM_RENDERFORMAT */
764 lpFormat
->hData16
= 0;
766 return lpFormat
->hData32
; /* Should we return lpFormat->hDataSrc32 */
770 /**************************************************************************
771 * GetClipboardData16 (USER.142)
773 HANDLE16 WINAPI
GetClipboardData16( UINT16 wFormat
)
775 LPWINE_CLIPFORMAT lpRender
= ClipFormats
;
777 TRACE("(%04X)\n", wFormat
);
779 if (CLIPBOARD_IsLocked())
781 WARN("Clipboard not opened by calling task!\n");
785 if( wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
)
787 lpRender
= CLIPBOARD_RenderText(wFormat
);
788 if ( !lpRender
) return 0;
792 lpRender
= __lookup_format( ClipFormats
, wFormat
);
793 if( !lpRender
|| !CLIPBOARD_RenderFormat(lpRender
) ) return 0;
796 /* Convert between 32 -> 16 bit data, if necessary */
797 if( lpRender
->hData32
&& !lpRender
->hData16
798 && CLIPBOARD_IsMemoryObject(wFormat
) )
801 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
802 size
= sizeof( METAFILEPICT16
);
804 size
= GlobalSize(lpRender
->hData32
);
806 lpRender
->hData16
= GlobalAlloc16(GMEM_ZEROINIT
, size
);
807 if( !lpRender
->hData16
)
808 ERR("(%04X) -- not enough memory in 16b heap\n", wFormat
);
811 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
813 FIXME("\timplement function CopyMetaFilePict32to16\n");
814 FIXME("\tin the appropriate file.\n");
815 #ifdef SOMEONE_IMPLEMENTED_ME
816 CopyMetaFilePict32to16( GlobalLock16(lpRender
->hData16
),
817 GlobalLock(lpRender
->hData32
) );
822 memcpy( GlobalLock16(lpRender
->hData16
),
823 GlobalLock(lpRender
->hData32
),
826 GlobalUnlock16(lpRender
->hData16
);
827 GlobalUnlock(lpRender
->hData32
);
831 TRACE("\treturning %04x (type %i)\n",
832 lpRender
->hData16
, lpRender
->wFormatID
);
833 return lpRender
->hData16
;
837 /**************************************************************************
838 * GetClipboardData32 (USER32.222)
840 HANDLE WINAPI
GetClipboardData( UINT wFormat
)
842 LPWINE_CLIPFORMAT lpRender
= ClipFormats
;
844 TRACE("(%08X)\n", wFormat
);
846 if (CLIPBOARD_IsLocked())
848 WARN("Clipboard not opened by calling task!");
852 if( wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
)
854 lpRender
= CLIPBOARD_RenderText(wFormat
);
855 if ( !lpRender
) return 0;
859 lpRender
= __lookup_format( ClipFormats
, wFormat
);
860 if( !lpRender
|| !CLIPBOARD_RenderFormat(lpRender
) ) return 0;
863 /* Convert between 16 -> 32 bit data, if necessary */
864 if( lpRender
->hData16
&& !lpRender
->hData32
865 && CLIPBOARD_IsMemoryObject(wFormat
) )
868 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
869 size
= sizeof( METAFILEPICT
);
871 size
= GlobalSize16(lpRender
->hData16
);
872 lpRender
->hData32
= GlobalAlloc(GMEM_ZEROINIT
| GMEM_MOVEABLE
| GMEM_DDESHARE
,
874 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
876 FIXME("\timplement function CopyMetaFilePict16to32\n");
877 FIXME("\tin the appropriate file.\n");
878 #ifdef SOMEONE_IMPLEMENTED_ME
879 CopyMetaFilePict16to32( GlobalLock16(lpRender
->hData32
),
880 GlobalLock(lpRender
->hData16
) );
885 memcpy( GlobalLock(lpRender
->hData32
),
886 GlobalLock16(lpRender
->hData16
),
889 GlobalUnlock(lpRender
->hData32
);
890 GlobalUnlock16(lpRender
->hData16
);
893 TRACE("\treturning %04x (type %i)\n",
894 lpRender
->hData32
, lpRender
->wFormatID
);
895 return lpRender
->hData32
;
899 /**************************************************************************
900 * CountClipboardFormats16 (USER.143)
902 INT16 WINAPI
CountClipboardFormats16(void)
904 return CountClipboardFormats();
908 /**************************************************************************
909 * CountClipboardFormats32 (USER32.63)
911 INT WINAPI
CountClipboardFormats(void)
914 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
920 if (lpFormat
== NULL
) break;
922 if( lpFormat
->wFormatID
!= CF_TEXT
) /* Don't count CF_TEXT */
925 * The format is available if either:
926 * 1. The data is already in the cache.
927 * 2. The selection is not owned by us(WINE) and the data is
928 * available to the clipboard driver.
930 if ( lpFormat
->wDataPresent
||
931 ( !CLIPBOARD_Driver
->pIsSelectionOwner()
932 && CLIPBOARD_Driver
->pIsFormatAvailable( lpFormat
->wFormatID
) ) )
934 TRACE("\tdata found for format 0x%04x(%s)\n",
935 lpFormat
->wFormatID
, CLIPBOARD_GetFormatName(lpFormat
->wFormatID
));
940 lpFormat
= lpFormat
->NextFormat
;
943 /* these two are equivalent, adjust the total */
945 FormatCount
+= abs(ClipFormats
[CF_TEXT
-1].wDataPresent
-
946 ClipFormats
[CF_OEMTEXT
-1].wDataPresent
);
948 TRACE("\ttotal %d\n", FormatCount
);
953 /**************************************************************************
954 * EnumClipboardFormats16 (USER.144)
956 UINT16 WINAPI
EnumClipboardFormats16( UINT16 wFormat
)
958 return EnumClipboardFormats( wFormat
);
962 /**************************************************************************
963 * EnumClipboardFormats32 (USER32.179)
965 UINT WINAPI
EnumClipboardFormats( UINT wFormat
)
967 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
970 TRACE("(%04X)\n", wFormat
);
972 if (CLIPBOARD_IsLocked())
974 WARN("Clipboard not opened by calling task!");
978 if (wFormat
== 0) /* start from the beginning */
979 lpFormat
= ClipFormats
;
982 /* walk up to the specified format record */
984 if( !(lpFormat
= __lookup_format( lpFormat
, wFormat
)) )
986 lpFormat
= lpFormat
->NextFormat
; /* right */
991 if (lpFormat
== NULL
) return 0;
993 /* Synthesize CF_TEXT from CF_OEMTEXT and vice versa */
994 bFormatPresent
= (lpFormat
->wDataPresent
||
995 (lpFormat
->wFormatID
== CF_OEMTEXT
&& ClipFormats
[CF_TEXT
-1].wDataPresent
) ||
996 (lpFormat
->wFormatID
== CF_TEXT
&& ClipFormats
[CF_OEMTEXT
-1].wDataPresent
) );
998 /* Query the driver if not yet in the cache */
999 if (!bFormatPresent
&& !CLIPBOARD_Driver
->pIsSelectionOwner())
1002 CLIPBOARD_Driver
->pIsFormatAvailable( (lpFormat
->wFormatID
== CF_TEXT
) ?
1003 CF_OEMTEXT
: lpFormat
->wFormatID
);
1009 lpFormat
= lpFormat
->NextFormat
;
1012 return lpFormat
->wFormatID
;
1016 /**************************************************************************
1017 * RegisterClipboardFormat16 (USER.145)
1019 UINT16 WINAPI
RegisterClipboardFormat16( LPCSTR FormatName
)
1021 LPWINE_CLIPFORMAT lpNewFormat
;
1022 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
1024 if (FormatName
== NULL
) return 0;
1026 TRACE("('%s') !\n", FormatName
);
1028 /* walk format chain to see if it's already registered */
1032 if ( !strcmp(lpFormat
->Name
,FormatName
) )
1034 lpFormat
->wRefCount
++;
1035 return lpFormat
->wFormatID
;
1038 if ( lpFormat
->NextFormat
== NULL
) break;
1040 lpFormat
= lpFormat
->NextFormat
;
1043 /* allocate storage for new format entry */
1045 lpNewFormat
= (LPWINE_CLIPFORMAT
)xmalloc(sizeof(WINE_CLIPFORMAT
));
1046 lpFormat
->NextFormat
= lpNewFormat
;
1047 lpNewFormat
->wFormatID
= LastRegFormat
;
1048 lpNewFormat
->wRefCount
= 1;
1050 lpNewFormat
->Name
= (LPSTR
)xmalloc(strlen(FormatName
) + 1);
1051 strcpy(lpNewFormat
->Name
, FormatName
);
1053 lpNewFormat
->wDataPresent
= 0;
1054 lpNewFormat
->hData16
= 0;
1055 lpNewFormat
->hDataSrc32
= 0;
1056 lpNewFormat
->hData32
= 0;
1057 lpNewFormat
->drvData
= 0;
1058 lpNewFormat
->PrevFormat
= lpFormat
;
1059 lpNewFormat
->NextFormat
= NULL
;
1061 /* Pass on the registration request to the driver */
1062 CLIPBOARD_Driver
->pRegisterFormat( FormatName
);
1064 return LastRegFormat
++;
1068 /**************************************************************************
1069 * RegisterClipboardFormat32A (USER32.431)
1071 UINT WINAPI
RegisterClipboardFormatA( LPCSTR formatName
)
1073 return RegisterClipboardFormat16( formatName
);
1077 /**************************************************************************
1078 * RegisterClipboardFormat32W (USER32.432)
1080 UINT WINAPI
RegisterClipboardFormatW( LPCWSTR formatName
)
1082 LPSTR aFormat
= HEAP_strdupWtoA( GetProcessHeap(), 0, formatName
);
1083 UINT ret
= RegisterClipboardFormatA( aFormat
);
1084 HeapFree( GetProcessHeap(), 0, aFormat
);
1089 /**************************************************************************
1090 * GetClipboardFormatName16 (USER.146)
1092 INT16 WINAPI
GetClipboardFormatName16( UINT16 wFormat
, LPSTR retStr
, INT16 maxlen
)
1094 return GetClipboardFormatNameA( wFormat
, retStr
, maxlen
);
1098 /**************************************************************************
1099 * GetClipboardFormatName32A (USER32.223)
1101 INT WINAPI
GetClipboardFormatNameA( UINT wFormat
, LPSTR retStr
, INT maxlen
)
1103 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
1105 TRACE("(%04X, %p, %d) !\n", wFormat
, retStr
, maxlen
);
1107 if (lpFormat
== NULL
|| lpFormat
->Name
== NULL
||
1108 lpFormat
->wFormatID
< CF_REGFORMATBASE
) return 0;
1110 TRACE("Name='%s' !\n", lpFormat
->Name
);
1112 lstrcpynA( retStr
, lpFormat
->Name
, maxlen
);
1113 return strlen(retStr
);
1117 /**************************************************************************
1118 * GetClipboardFormatName32W (USER32.224)
1120 INT WINAPI
GetClipboardFormatNameW( UINT wFormat
, LPWSTR retStr
, INT maxlen
)
1122 LPSTR p
= HEAP_xalloc( GetProcessHeap(), 0, maxlen
);
1123 INT ret
= GetClipboardFormatNameA( wFormat
, p
, maxlen
);
1124 lstrcpynAtoW( retStr
, p
, maxlen
);
1125 HeapFree( GetProcessHeap(), 0, p
);
1130 /**************************************************************************
1131 * SetClipboardViewer16 (USER.147)
1133 HWND16 WINAPI
SetClipboardViewer16( HWND16 hWnd
)
1135 TRACE("(%04x)\n", hWnd
);
1136 return SetClipboardViewer( hWnd
);
1140 /**************************************************************************
1141 * SetClipboardViewer32 (USER32.471)
1143 HWND WINAPI
SetClipboardViewer( HWND hWnd
)
1145 HWND hwndPrev
= hWndViewer
;
1147 TRACE("(%04x): returning %04x\n", hWnd
, hwndPrev
);
1154 /**************************************************************************
1155 * GetClipboardViewer16 (USER.148)
1157 HWND16 WINAPI
GetClipboardViewer16(void)
1164 /**************************************************************************
1165 * GetClipboardViewer32 (USER32.226)
1167 HWND WINAPI
GetClipboardViewer(void)
1174 /**************************************************************************
1175 * ChangeClipboardChain16 (USER.149)
1177 BOOL16 WINAPI
ChangeClipboardChain16(HWND16 hWnd
, HWND16 hWndNext
)
1179 return ChangeClipboardChain(hWnd
, hWndNext
);
1183 /**************************************************************************
1184 * ChangeClipboardChain32 (USER32.22)
1186 BOOL WINAPI
ChangeClipboardChain(HWND hWnd
, HWND hWndNext
)
1190 FIXME("(0x%04x, 0x%04x): stub?\n", hWnd
, hWndNext
);
1193 bRet
= !SendMessage16( hWndViewer
, WM_CHANGECBCHAIN
,
1194 (WPARAM16
)hWnd
, (LPARAM
)hWndNext
);
1196 WARN("hWndViewer is lost\n");
1198 if( hWnd
== hWndViewer
) hWndViewer
= hWndNext
;
1204 /**************************************************************************
1205 * IsClipboardFormatAvailable16 (USER.193)
1207 BOOL16 WINAPI
IsClipboardFormatAvailable16( UINT16 wFormat
)
1209 return IsClipboardFormatAvailable( wFormat
);
1213 /**************************************************************************
1214 * IsClipboardFormatAvailable32 (USER32.340)
1216 BOOL WINAPI
IsClipboardFormatAvailable( UINT wFormat
)
1220 if (wFormat
== 0) /* Reject this case quickly */
1223 /* If WINE is not the clipboard selection owner ask the clipboard driver */
1224 else if ( !CLIPBOARD_Driver
->pIsSelectionOwner() )
1225 bRet
= CLIPBOARD_Driver
->pIsFormatAvailable( (wFormat
== CF_TEXT
) ?
1226 CF_OEMTEXT
: wFormat
);
1227 /* Check if the format is in the local cache */
1229 bRet
= CLIPBOARD_IsPresent(wFormat
);
1231 TRACE("(%04X)- ret(%d)\n", wFormat
, bRet
);
1236 /**************************************************************************
1237 * GetOpenClipboardWindow16 (USER.248)
1238 * FIXME: This wont work if an external app owns the selection
1240 HWND16 WINAPI
GetOpenClipboardWindow16(void)
1243 return hWndClipWindow
;
1247 /**************************************************************************
1248 * GetOpenClipboardWindow32 (USER32.277)
1249 * FIXME: This wont work if an external app owns the selection
1251 HWND WINAPI
GetOpenClipboardWindow(void)
1254 return hWndClipWindow
;
1258 /**************************************************************************
1259 * GetPriorityClipboardFormat16 (USER.402)
1261 INT16 WINAPI
GetPriorityClipboardFormat16( UINT16
*lpPriorityList
, INT16 nCount
)
1263 FIXME("(%p,%d): stub\n", lpPriorityList
, nCount
);
1268 /**************************************************************************
1269 * GetPriorityClipboardFormat32 (USER32.279)
1271 INT WINAPI
GetPriorityClipboardFormat( UINT
*lpPriorityList
, INT nCount
)
1276 if(CountClipboardFormats() == 0)
1281 for(Counter
= 0; Counter
<= nCount
; Counter
++)
1283 if(IsClipboardFormatAvailable(*(lpPriorityList
+sizeof(INT
)*Counter
)))
1284 return *(lpPriorityList
+sizeof(INT
)*Counter
);