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)
18 #include <sys/types.h>
27 #include "wine/winuser16.h"
28 #include "wine/winbase16.h"
32 #include "clipboard.h"
33 #include "debugtools.h"
35 DEFAULT_DEBUG_CHANNEL(clipboard
);
37 #define CF_REGFORMATBASE 0xC000
39 /**************************************************************************
40 * Clipboard context global variables
43 static HANDLE hClipLock
= 0;
44 static BOOL bCBHasChanged
= FALSE
;
46 static HWND hWndClipWindow
; /* window that last opened clipboard */
47 static HWND hWndClipOwner
; /* current clipboard owner */
48 static HANDLE16 hTaskClipOwner
; /* clipboard owner's task */
49 static HWND hWndViewer
; /* start of viewers chain */
51 static WORD LastRegFormat
= CF_REGFORMATBASE
;
53 /* Clipboard cache initial data.
54 * WARNING: This data ordering is dependent on the WINE_CLIPFORMAT structure
55 * declared in clipboard.h
57 WINE_CLIPFORMAT ClipFormats
[] = {
58 { CF_TEXT
, 1, 0, "Text", 0, 0, 0, 0, NULL
, &ClipFormats
[1]},
59 { CF_BITMAP
, 1, 0, "Bitmap", 0, 0, 0, 0, &ClipFormats
[0], &ClipFormats
[2]},
60 { CF_METAFILEPICT
, 1, 0, "MetaFile Picture", 0, 0, 0, 0, &ClipFormats
[1], &ClipFormats
[3]},
61 { CF_SYLK
, 1, 0, "Sylk", 0, 0, 0, 0, &ClipFormats
[2], &ClipFormats
[4]},
62 { CF_DIF
, 1, 0, "DIF", 0, 0, 0, 0, &ClipFormats
[3], &ClipFormats
[5]},
63 { CF_TIFF
, 1, 0, "TIFF", 0, 0, 0, 0, &ClipFormats
[4], &ClipFormats
[6]},
64 { CF_OEMTEXT
, 1, 0, "OEM Text", 0, 0, 0, 0, &ClipFormats
[5], &ClipFormats
[7]},
65 { CF_DIB
, 1, 0, "DIB", 0, 0, 0, 0, &ClipFormats
[6], &ClipFormats
[8]},
66 { CF_PALETTE
, 1, 0, "Palette", 0, 0, 0, 0, &ClipFormats
[7], &ClipFormats
[9]},
67 { CF_PENDATA
, 1, 0, "PenData", 0, 0, 0, 0, &ClipFormats
[8], &ClipFormats
[10]},
68 { CF_RIFF
, 1, 0, "RIFF", 0, 0, 0, 0, &ClipFormats
[9], &ClipFormats
[11]},
69 { CF_WAVE
, 1, 0, "Wave", 0, 0, 0, 0, &ClipFormats
[10], &ClipFormats
[12]},
70 { CF_UNICODETEXT
, 1, 0, "Unicode Text", 0, 0, 0, 0, &ClipFormats
[11], &ClipFormats
[13]},
71 { CF_OWNERDISPLAY
, 1, 0, "Owner Display", 0, 0, 0, 0, &ClipFormats
[12], &ClipFormats
[14]},
72 { CF_DSPTEXT
, 1, 0, "DSPText", 0, 0, 0, 0, &ClipFormats
[13], &ClipFormats
[15]},
73 { CF_DSPMETAFILEPICT
, 1, 0, "DSPMetaFile Picture", 0, 0, 0, 0, &ClipFormats
[14], &ClipFormats
[16]},
74 { CF_DSPBITMAP
, 1, 0, "DSPBitmap", 0, 0, 0, 0, &ClipFormats
[15], &ClipFormats
[17]},
75 { CF_HDROP
, 1, 0, "HDROP", 0, 0, 0, 0, &ClipFormats
[16], NULL
}
79 /**************************************************************************
80 * Internal Clipboard implementation methods
81 **************************************************************************/
84 /**************************************************************************
85 * CLIPBOARD_LookupFormat
87 static LPWINE_CLIPFORMAT
__lookup_format( LPWINE_CLIPFORMAT lpFormat
, WORD wID
)
91 if (lpFormat
== NULL
||
92 lpFormat
->wFormatID
== wID
) break;
93 lpFormat
= lpFormat
->NextFormat
;
98 LPWINE_CLIPFORMAT
CLIPBOARD_LookupFormat( WORD wID
)
100 return __lookup_format( ClipFormats
, wID
);
103 /**************************************************************************
105 * Check if the clipboard cache is available to the caller
107 BOOL
CLIPBOARD_IsLocked()
109 BOOL bIsLocked
= TRUE
;
110 HANDLE16 hTaskCur
= GetCurrentTask();
113 * The clipboard is available:
114 * 1. if the caller's task has opened the clipboard,
116 * 2. if the caller is the clipboard owners task, AND is responding to a
117 * WM_RENDERFORMAT message.
119 if ( hClipLock
== hTaskCur
)
122 else if ( hTaskCur
== hTaskClipOwner
)
124 /* Check if we're currently executing inside a window procedure
125 * called in response to a WM_RENDERFORMAT message. A WM_RENDERFORMAT
126 * handler is not permitted to open the clipboard since it has been opened
127 * by another client. However the handler must have access to the
128 * clipboard in order to update data in response to this message.
131 MESSAGEQUEUE
*queue
= QUEUE_Current();
135 && queue
->smWaiting
->msg
== WM_RENDERFORMAT
136 && queue
->smWaiting
->hSrcQueue
140 /* FIXME: queue check no longer possible */
148 /**************************************************************************
149 * CLIPBOARD_ReleaseOwner
150 * Gives up ownership of the clipboard
152 void CLIPBOARD_ReleaseOwner()
158 /**************************************************************************
159 * CLIPBOARD_GlobalFreeProc
161 * This is a callback mechanism to allow HGLOBAL data to be released in
162 * the context of the process which allocated it. We post a WM_TIMER message
163 * to the owner window(in CLIPBOARD_DeleteRecord) and destroy the data(in idEvent)
164 * in this WndProc, which is invoked when the apps message loop calls DispatchMessage.
165 * This technique is discussed in Matt Pietrek's "Under the Hood".
166 * An article describing the same may be found in MSDN by searching for WM_TIMER.
167 * Note that this mechanism will probably stop working when WINE supports
168 * address space separation. When "queue events" are implemented in Wine we
169 * should switch to using that mechanism, since it is more robust and does not
170 * require a procedure address to be passed. See the SetWinEventHook API for
173 VOID CALLBACK
CLIPBOARD_GlobalFreeProc( HWND hwnd
, UINT uMsg
, UINT idEvent
, DWORD dwTime
)
175 /* idEvent is the HGLOBAL to be deleted */
176 GlobalFree( (HGLOBAL
)idEvent
);
179 /**************************************************************************
180 * CLIPBOARD_DeleteRecord
182 void CLIPBOARD_DeleteRecord(LPWINE_CLIPFORMAT lpFormat
, BOOL bChange
)
184 if( (lpFormat
->wFormatID
>= CF_GDIOBJFIRST
&&
185 lpFormat
->wFormatID
<= CF_GDIOBJLAST
) || lpFormat
->wFormatID
== CF_BITMAP
186 || lpFormat
->wFormatID
== CF_PALETTE
)
188 if (lpFormat
->hData32
)
189 DeleteObject(lpFormat
->hData32
);
190 if (lpFormat
->hData16
)
191 DeleteObject(lpFormat
->hData16
);
193 else if( lpFormat
->wFormatID
== CF_METAFILEPICT
)
195 if (lpFormat
->hData32
)
197 DeleteMetaFile( ((METAFILEPICT
*)GlobalLock( lpFormat
->hData32
))->hMF
);
198 PostMessageA(hWndClipOwner
, WM_TIMER
,
199 (WPARAM
)lpFormat
->hData32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
200 if (lpFormat
->hDataSrc32
)
202 /* Release lpFormat->hData32 in the context of the process which created it.
203 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
204 * GlobalFree(lpFormat->hDataSrc32);
206 PostMessageA(hWndClipOwner
, WM_TIMER
,
207 (WPARAM
)lpFormat
->hDataSrc32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
210 if (lpFormat
->hData16
)
211 /* HMETAFILE16 and HMETAFILE32 are apparently the same thing,
212 and a shallow copy is enough to share a METAFILEPICT
213 structure between 16bit and 32bit clipboards. The MetaFile
214 should of course only be deleted once. */
215 GlobalFree16(lpFormat
->hData16
);
217 if (lpFormat
->hData16
)
219 DeleteMetaFile16( ((METAFILEPICT16
*)GlobalLock16( lpFormat
->hData16
))->hMF
);
220 GlobalFree16(lpFormat
->hData16
);
225 if (lpFormat
->hData32
)
227 /* Release lpFormat->hData32 in the context of the process which created it.
228 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
229 * GlobalFree( lpFormat->hData32 );
231 PostMessageA(hWndClipOwner
, WM_TIMER
,
232 (WPARAM
)lpFormat
->hData32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
234 if (lpFormat
->hDataSrc32
)
236 /* Release lpFormat->hData32 in the context of the process which created it.
237 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
238 * GlobalFree(lpFormat->hDataSrc32);
240 PostMessageA(hWndClipOwner
, WM_TIMER
,
241 (WPARAM
)lpFormat
->hDataSrc32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
243 if (lpFormat
->hData16
)
244 GlobalFree16(lpFormat
->hData16
);
247 lpFormat
->wDataPresent
= 0;
248 lpFormat
->hData16
= 0;
249 lpFormat
->hData32
= 0;
250 lpFormat
->hDataSrc32
= 0;
251 lpFormat
->drvData
= 0;
253 if( bChange
) bCBHasChanged
= TRUE
;
256 /**************************************************************************
257 * CLIPBOARD_EmptyCache
259 void CLIPBOARD_EmptyCache( BOOL bChange
)
261 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
265 if ( lpFormat
->wDataPresent
|| lpFormat
->hData16
|| lpFormat
->hData32
)
266 CLIPBOARD_DeleteRecord( lpFormat
, bChange
);
268 lpFormat
= lpFormat
->NextFormat
;
272 /**************************************************************************
273 * CLIPBOARD_IsPresent
275 BOOL
CLIPBOARD_IsPresent(WORD wFormat
)
279 if( wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
|| wFormat
== CF_UNICODETEXT
)
280 return ClipFormats
[CF_TEXT
-1].wDataPresent
||
281 ClipFormats
[CF_OEMTEXT
-1].wDataPresent
||
282 ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
;
285 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
286 if( lpFormat
) return (lpFormat
->wDataPresent
);
291 /**************************************************************************
292 * CLIPBOARD_IsCacheRendered
293 * Checks if any data needs to be rendered to the clipboard cache
295 * TRUE - All clipboard data is available in the cache
296 * FALSE - Some data is marked for delayed render and needs rendering
298 BOOL
CLIPBOARD_IsCacheRendered()
300 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
302 /* check if all formats were rendered */
305 if( lpFormat
->wDataPresent
&& !lpFormat
->hData16
&& !lpFormat
->hData32
)
308 lpFormat
= lpFormat
->NextFormat
;
315 /**************************************************************************
316 * CLIPBOARD_IsMemoryObject
317 * Tests if the clipboard format specifies a memory object
319 BOOL
CLIPBOARD_IsMemoryObject( WORD wFormat
)
324 case CF_METAFILEPICT
:
336 /***********************************************************************
337 * CLIPBOARD_GlobalDupMem( HGLOBAL )
338 * Helper method to duplicate an HGLOBAL chunk of memory into shared memory
340 HGLOBAL
CLIPBOARD_GlobalDupMem( HGLOBAL hGlobalSrc
)
343 PVOID pGlobalSrc
, pGlobalDest
;
349 cBytes
= GlobalSize(hGlobalSrc
);
353 /* Turn on the DDESHARE and _MOVEABLE flags explicitly */
354 hGlobalDest
= GlobalAlloc( GlobalFlags(hGlobalSrc
) | GMEM_DDESHARE
| GMEM_MOVEABLE
,
359 pGlobalSrc
= GlobalLock(hGlobalSrc
);
360 pGlobalDest
= GlobalLock(hGlobalDest
);
361 if ( !pGlobalSrc
|| !pGlobalDest
)
364 memcpy(pGlobalDest
, pGlobalSrc
, cBytes
);
366 GlobalUnlock(hGlobalSrc
);
367 GlobalUnlock(hGlobalDest
);
372 /**************************************************************************
373 * CLIPBOARD_GetFormatName
374 * Gets the format name associated with an ID
376 char * CLIPBOARD_GetFormatName(UINT wFormat
)
378 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
379 return (lpFormat
) ? lpFormat
->Name
: NULL
;
383 /**************************************************************************
384 * CLIPBOARD_RenderFormat
386 static BOOL
CLIPBOARD_RenderFormat(LPWINE_CLIPFORMAT lpFormat
)
389 * If WINE is not the selection owner, and the format is available
390 * we must ask the driver to render the data to the clipboard cache.
392 TRACE("enter format=%d\n", lpFormat
->wFormatID
);
393 if ( !USER_Driver
.pIsSelectionOwner()
394 && USER_Driver
.pIsClipboardFormatAvailable( lpFormat
->wFormatID
) )
396 if ( !USER_Driver
.pGetClipboardData( 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 SendMessageW( hWndClipOwner
, WM_RENDERFORMAT
, (WPARAM
)lpFormat
->wFormatID
, 0 );
415 WARN("\thWndClipOwner (%04x) is lost!\n",
417 CLIPBOARD_ReleaseOwner();
418 lpFormat
->wDataPresent
= 0;
423 return (lpFormat
->hData16
|| lpFormat
->hData32
) ? TRUE
: FALSE
;
426 /**************************************************************************
427 * CLIPBOARD_ConvertText
428 * Returns number of required/converted characters - not bytes!
430 static INT
CLIPBOARD_ConvertText(WORD src_fmt
, void const *src
, INT src_size
,
431 WORD dst_fmt
, void *dst
, INT dst_size
)
435 if(src_fmt
== CF_UNICODETEXT
)
448 return WideCharToMultiByte(cp
, 0, src
, src_size
, dst
, dst_size
, NULL
, NULL
);
451 if(dst_fmt
== CF_UNICODETEXT
)
464 return MultiByteToWideChar(cp
, 0, src
, src_size
, dst
, dst_size
);
467 if(!dst_size
) return src_size
;
469 if(dst_size
> src_size
) dst_size
= src_size
;
471 if(src_fmt
== CF_TEXT
)
472 CharToOemBuffA(src
, dst
, dst_size
);
474 OemToCharBuffA(src
, dst
, dst_size
);
479 /**************************************************************************
480 * CLIPBOARD_RenderText
482 * Renders text to the clipboard buffer converting between UNIX and DOS formats.
484 * RETURNS: pointer to the WINE_CLIPFORMAT if successful, NULL otherwise
486 * FIXME: Should be a pair of driver functions that convert between OEM text and Windows.
489 static LPWINE_CLIPFORMAT
CLIPBOARD_RenderText( UINT wFormat
)
491 LPWINE_CLIPFORMAT lpSource
= ClipFormats
;
492 LPWINE_CLIPFORMAT lpTarget
= NULL
;
493 BOOL foundData
= FALSE
;
495 /* Asked for CF_TEXT */
496 if( wFormat
== CF_TEXT
)
498 if(ClipFormats
[CF_TEXT
-1].wDataPresent
)
500 lpSource
= &ClipFormats
[CF_TEXT
-1];
501 lpTarget
= &ClipFormats
[CF_TEXT
-1];
503 TRACE("\t TEXT -> TEXT\n");
505 else if(ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
)
507 /* Convert UNICODETEXT -> TEXT */
508 lpSource
= &ClipFormats
[CF_UNICODETEXT
-1];
509 lpTarget
= &ClipFormats
[CF_TEXT
-1];
511 TRACE("\tUNICODETEXT -> TEXT\n");
513 else if(ClipFormats
[CF_OEMTEXT
-1].wDataPresent
)
515 /* Convert OEMTEXT -> TEXT */
516 lpSource
= &ClipFormats
[CF_OEMTEXT
-1];
517 lpTarget
= &ClipFormats
[CF_TEXT
-1];
519 TRACE("\tOEMTEXT -> TEXT\n");
522 /* Asked for CF_OEMTEXT */
523 else if( wFormat
== CF_OEMTEXT
)
525 if(ClipFormats
[CF_OEMTEXT
-1].wDataPresent
)
527 lpSource
= &ClipFormats
[CF_OEMTEXT
-1];
528 lpTarget
= &ClipFormats
[CF_OEMTEXT
-1];
530 TRACE("\tOEMTEXT -> OEMTEXT\n");
532 else if(ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
)
534 /* Convert UNICODETEXT -> OEMTEXT */
535 lpSource
= &ClipFormats
[CF_UNICODETEXT
-1];
536 lpTarget
= &ClipFormats
[CF_OEMTEXT
-1];
538 TRACE("\tUNICODETEXT -> OEMTEXT\n");
540 else if(ClipFormats
[CF_TEXT
-1].wDataPresent
)
542 /* Convert TEXT -> OEMTEXT */
543 lpSource
= &ClipFormats
[CF_TEXT
-1];
544 lpTarget
= &ClipFormats
[CF_OEMTEXT
-1];
546 TRACE("\tTEXT -> OEMTEXT\n");
549 /* Asked for CF_UNICODETEXT */
550 else if( wFormat
== CF_UNICODETEXT
)
552 if(ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
)
554 lpSource
= &ClipFormats
[CF_UNICODETEXT
-1];
555 lpTarget
= &ClipFormats
[CF_UNICODETEXT
-1];
557 TRACE("\tUNICODETEXT -> UNICODETEXT\n");
559 else if(ClipFormats
[CF_TEXT
-1].wDataPresent
)
561 /* Convert TEXT -> UNICODETEXT */
562 lpSource
= &ClipFormats
[CF_TEXT
-1];
563 lpTarget
= &ClipFormats
[CF_UNICODETEXT
-1];
565 TRACE("\tTEXT -> UNICODETEXT\n");
567 else if(ClipFormats
[CF_OEMTEXT
-1].wDataPresent
)
569 /* Convert OEMTEXT -> UNICODETEXT */
570 lpSource
= &ClipFormats
[CF_OEMTEXT
-1];
571 lpTarget
= &ClipFormats
[CF_UNICODETEXT
-1];
573 TRACE("\tOEMTEXT -> UNICODETEXT\n");
578 if ((wFormat
== CF_TEXT
) || (wFormat
== CF_OEMTEXT
))
580 lpSource
= &ClipFormats
[CF_UNICODETEXT
-1];
581 lpTarget
= __lookup_format( ClipFormats
, wFormat
);
585 lpSource
= __lookup_format( ClipFormats
, wFormat
);
590 /* First render the source text format */
591 if ( !lpSource
|| !CLIPBOARD_RenderFormat(lpSource
) ) return NULL
;
593 /* Convert to the desired target text format, if necessary */
594 if( lpTarget
!= lpSource
&& !lpTarget
->hData16
&& !lpTarget
->hData32
)
596 INT src_chars
, dst_chars
, alloc_size
;
600 if (lpSource
->hData32
)
602 lpstrS
= (LPSTR
)GlobalLock(lpSource
->hData32
);
606 lpstrS
= (LPSTR
)GlobalLock16(lpSource
->hData16
);
609 if( !lpstrS
) return NULL
;
611 /* Text always NULL terminated */
612 if(lpSource
->wFormatID
== CF_UNICODETEXT
)
613 src_chars
= strlenW((LPCWSTR
)lpstrS
)+1;
615 src_chars
= strlen(lpstrS
)+1;
617 /* Calculate number of characters in the destination buffer */
618 dst_chars
= CLIPBOARD_ConvertText(lpSource
->wFormatID
, lpstrS
, src_chars
,
619 lpTarget
->wFormatID
, NULL
, 0);
620 if(!dst_chars
) return NULL
;
622 TRACE("\tconverting from '%s' to '%s', %i chars\n",
623 lpSource
->Name
, lpTarget
->Name
, src_chars
);
625 /* Convert characters to bytes */
626 if(lpTarget
->wFormatID
== CF_UNICODETEXT
)
627 alloc_size
= dst_chars
* sizeof(WCHAR
);
629 alloc_size
= dst_chars
;
631 lpTarget
->hData32
= GlobalAlloc(GMEM_ZEROINIT
| GMEM_MOVEABLE
| GMEM_DDESHARE
, alloc_size
);
632 lpstrT
= (LPSTR
)GlobalLock(lpTarget
->hData32
);
636 CLIPBOARD_ConvertText(lpSource
->wFormatID
, lpstrS
, src_chars
,
637 lpTarget
->wFormatID
, lpstrT
, dst_chars
);
638 GlobalUnlock(lpTarget
->hData32
);
641 lpTarget
->hData32
= 0;
644 if (lpSource
->hData32
)
645 GlobalUnlock(lpSource
->hData32
);
647 GlobalUnlock16(lpSource
->hData16
);
650 return (lpTarget
->hData16
|| lpTarget
->hData32
) ? lpTarget
: NULL
;
653 /**************************************************************************
654 * CLIPBOARD_EnumClipboardFormats (internal)
656 static UINT
CLIPBOARD_EnumClipboardFormats( UINT wFormat
)
658 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
661 if (wFormat
== 0) /* start from the beginning */
662 lpFormat
= ClipFormats
;
665 /* walk up to the specified format record */
667 if( !(lpFormat
= __lookup_format( lpFormat
, wFormat
)) )
669 lpFormat
= lpFormat
->NextFormat
; /* right */
674 if (lpFormat
== NULL
) return 0;
676 if(CLIPBOARD_IsPresent(lpFormat
->wFormatID
))
679 /* Query the driver if not yet in the cache */
680 if (!USER_Driver
.pIsSelectionOwner())
682 if(lpFormat
->wFormatID
== CF_UNICODETEXT
||
683 lpFormat
->wFormatID
== CF_TEXT
||
684 lpFormat
->wFormatID
== CF_OEMTEXT
)
686 if(USER_Driver
.pIsClipboardFormatAvailable(CF_UNICODETEXT
) ||
687 USER_Driver
.pIsClipboardFormatAvailable(CF_TEXT
) ||
688 USER_Driver
.pIsClipboardFormatAvailable(CF_OEMTEXT
))
689 bFormatPresent
= TRUE
;
691 bFormatPresent
= FALSE
;
694 bFormatPresent
= USER_Driver
.pIsClipboardFormatAvailable(lpFormat
->wFormatID
);
700 lpFormat
= lpFormat
->NextFormat
;
703 TRACE("Next available format %d\n", lpFormat
->wFormatID
);
705 return lpFormat
->wFormatID
;
709 /**************************************************************************
710 * WIN32 Clipboard implementation
711 **************************************************************************/
713 /**************************************************************************
714 * OpenClipboard (USER32.@)
716 * Note: Netscape uses NULL hWnd to open the clipboard.
718 BOOL WINAPI
OpenClipboard( HWND hWnd
)
722 TRACE("(%04x)...\n", hWnd
);
726 hClipLock
= GetCurrentTask();
728 /* Save current user of the clipboard */
729 hWndClipWindow
= WIN_GetFullHandle( hWnd
);
730 bCBHasChanged
= FALSE
;
735 TRACE(" returning %i\n", bRet
);
740 /**************************************************************************
741 * CloseClipboard (USER.138)
743 BOOL16 WINAPI
CloseClipboard16(void)
745 return CloseClipboard();
749 /**************************************************************************
750 * CloseClipboard (USER32.@)
752 BOOL WINAPI
CloseClipboard(void)
756 if (hClipLock
== GetCurrentTask())
760 if (bCBHasChanged
&& hWndViewer
) SendMessageW( hWndViewer
, WM_DRAWCLIPBOARD
, 0, 0 );
767 /**************************************************************************
768 * EmptyClipboard (USER.139)
770 BOOL16 WINAPI
EmptyClipboard16(void)
772 return EmptyClipboard();
776 /**************************************************************************
777 * EmptyClipboard (USER32.@)
778 * Empties and acquires ownership of the clipboard
780 BOOL WINAPI
EmptyClipboard(void)
784 if (hClipLock
!= GetCurrentTask())
786 WARN("Clipboard not opened by calling task!\n");
790 /* destroy private objects */
792 if (hWndClipOwner
) SendMessageW( hWndClipOwner
, WM_DESTROYCLIPBOARD
, 0, 0 );
794 /* empty the cache */
795 CLIPBOARD_EmptyCache(TRUE
);
797 /* Assign ownership of the clipboard to the current client */
798 hWndClipOwner
= hWndClipWindow
;
800 /* Save the current task */
801 hTaskClipOwner
= GetCurrentTask();
803 /* Tell the driver to acquire the selection */
804 USER_Driver
.pAcquireClipboard();
810 /**************************************************************************
811 * GetClipboardOwner (USER32.@)
812 * FIXME: Can't return the owner if the clipbard is owned by an external app
814 HWND WINAPI
GetClipboardOwner(void)
817 return hWndClipOwner
;
821 /**************************************************************************
822 * SetClipboardData (USER.141)
824 HANDLE16 WINAPI
SetClipboardData16( UINT16 wFormat
, HANDLE16 hData
)
826 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
828 TRACE("(%04X, %04x) !\n", wFormat
, hData
);
830 /* NOTE: If the hData is zero and current owner doesn't match
831 * the window that opened the clipboard then this application
832 * is screwed because WM_RENDERFORMAT will go to the owner.
833 * (to become the owner it must call EmptyClipboard() before
837 if( CLIPBOARD_IsLocked() || !lpFormat
||
838 (!hData
&& (!hWndClipOwner
|| (hWndClipOwner
!= hWndClipWindow
))) )
840 WARN("Invalid hData or clipboard not opened by calling task!\n");
844 /* Pass on the request to the driver */
845 USER_Driver
.pSetClipboardData(wFormat
);
847 if ( lpFormat
->wDataPresent
|| lpFormat
->hData16
|| lpFormat
->hData32
)
849 CLIPBOARD_DeleteRecord(lpFormat
, TRUE
);
851 /* delete existing CF_UNICODETEXT/CF_TEXT/CF_OEMTEXT aliases */
852 if(wFormat
== CF_UNICODETEXT
)
854 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
855 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
857 else if(wFormat
== CF_TEXT
)
859 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_UNICODETEXT
-1], TRUE
);
860 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
862 else if(wFormat
== CF_OEMTEXT
)
864 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_UNICODETEXT
-1], TRUE
);
865 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
869 bCBHasChanged
= TRUE
;
870 lpFormat
->wDataPresent
= 1;
871 lpFormat
->hData16
= hData
; /* 0 is legal, see WM_RENDERFORMAT */
872 lpFormat
->hData32
= 0;
874 return lpFormat
->hData16
;
878 /**************************************************************************
879 * SetClipboardData (USER32.@)
881 HANDLE WINAPI
SetClipboardData( UINT wFormat
, HANDLE hData
)
883 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
885 TRACE("(%08X, %08x) !\n", wFormat
, hData
);
887 /* NOTE: If the hData is zero and current owner doesn't match
888 * the window that opened the clipboard then this application
889 * is screwed because WM_RENDERFORMAT will go to the owner.
890 * (to become the owner it must call EmptyClipboard() before
894 if( CLIPBOARD_IsLocked() || !lpFormat
||
895 (!hData
&& (!hWndClipOwner
|| (hWndClipOwner
!= hWndClipWindow
))) )
897 WARN("Invalid hData or clipboard not opened by calling task!\n");
901 /* Tell the driver to acquire the selection */
902 USER_Driver
.pAcquireClipboard();
904 if ( lpFormat
->wDataPresent
&&
905 (lpFormat
->hData16
|| lpFormat
->hData32
) )
907 CLIPBOARD_DeleteRecord(lpFormat
, TRUE
);
909 /* delete existing CF_UNICODETEXT/CF_TEXT/CF_OEMTEXT aliases */
910 if(wFormat
== CF_UNICODETEXT
)
912 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
913 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
915 else if(wFormat
== CF_TEXT
)
917 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_UNICODETEXT
-1], TRUE
);
918 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
920 else if(wFormat
== CF_OEMTEXT
)
922 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_UNICODETEXT
-1], TRUE
);
923 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
927 bCBHasChanged
= TRUE
;
928 lpFormat
->wDataPresent
= 1;
929 lpFormat
->hDataSrc32
= hData
; /* Save the source handle */
932 * Make a shared duplicate if the memory is not shared
933 * TODO: What should be done for non-memory objects
935 if ( CLIPBOARD_IsMemoryObject(wFormat
) && hData
&& !(GlobalFlags(hData
) & GMEM_DDESHARE
) )
936 lpFormat
->hData32
= CLIPBOARD_GlobalDupMem( hData
);
938 lpFormat
->hData32
= hData
; /* 0 is legal, see WM_RENDERFORMAT */
940 lpFormat
->hData16
= 0;
942 return lpFormat
->hData32
; /* Should we return lpFormat->hDataSrc32 */
946 /**************************************************************************
947 * GetClipboardData (USER.142)
949 HANDLE16 WINAPI
GetClipboardData16( UINT16 wFormat
)
951 LPWINE_CLIPFORMAT lpRender
= ClipFormats
;
953 TRACE("(%04X)\n", wFormat
);
955 if (CLIPBOARD_IsLocked())
957 WARN("Clipboard not opened by calling task!\n");
961 if( wFormat
== CF_UNICODETEXT
|| wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
)
963 lpRender
= CLIPBOARD_RenderText(wFormat
);
964 if ( !lpRender
) return 0;
968 lpRender
= __lookup_format( ClipFormats
, wFormat
);
969 if( !lpRender
|| !CLIPBOARD_RenderFormat(lpRender
) ) return 0;
972 /* Convert between 32 -> 16 bit data, if necessary */
973 if( lpRender
->hData32
&& !lpRender
->hData16
974 && CLIPBOARD_IsMemoryObject(wFormat
) )
977 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
978 size
= sizeof( METAFILEPICT16
);
980 size
= GlobalSize(lpRender
->hData32
);
982 lpRender
->hData16
= GlobalAlloc16(GMEM_ZEROINIT
, size
);
983 if( !lpRender
->hData16
)
984 ERR("(%04X) -- not enough memory in 16b heap\n", wFormat
);
987 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
989 FIXME("\timplement function CopyMetaFilePict32to16\n");
990 FIXME("\tin the appropriate file.\n");
991 #ifdef SOMEONE_IMPLEMENTED_ME
992 CopyMetaFilePict32to16( GlobalLock16(lpRender
->hData16
),
993 GlobalLock(lpRender
->hData32
) );
998 memcpy( GlobalLock16(lpRender
->hData16
),
999 GlobalLock(lpRender
->hData32
),
1002 GlobalUnlock16(lpRender
->hData16
);
1003 GlobalUnlock(lpRender
->hData32
);
1007 TRACE("\treturning %04x (type %i)\n",
1008 lpRender
->hData16
, lpRender
->wFormatID
);
1009 return lpRender
->hData16
;
1013 /**************************************************************************
1014 * GetClipboardData (USER32.@)
1016 HANDLE WINAPI
GetClipboardData( UINT wFormat
)
1018 LPWINE_CLIPFORMAT lpRender
= ClipFormats
;
1020 TRACE("(%08X)\n", wFormat
);
1022 if (CLIPBOARD_IsLocked())
1024 WARN("Clipboard not opened by calling task!\n");
1028 if( wFormat
== CF_UNICODETEXT
|| wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
)
1030 lpRender
= CLIPBOARD_RenderText(wFormat
);
1031 if ( !lpRender
) return 0;
1035 lpRender
= __lookup_format( ClipFormats
, wFormat
);
1036 if( !lpRender
|| !CLIPBOARD_RenderFormat(lpRender
) ) return 0;
1039 /* Convert between 16 -> 32 bit data, if necessary */
1040 if( lpRender
->hData16
&& !lpRender
->hData32
1041 && CLIPBOARD_IsMemoryObject(wFormat
) )
1044 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
1045 size
= sizeof( METAFILEPICT
);
1047 size
= GlobalSize16(lpRender
->hData16
);
1048 lpRender
->hData32
= GlobalAlloc(GMEM_ZEROINIT
| GMEM_MOVEABLE
| GMEM_DDESHARE
,
1050 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
1052 FIXME("\timplement function CopyMetaFilePict16to32\n");
1053 FIXME("\tin the appropriate file.\n");
1054 #ifdef SOMEONE_IMPLEMENTED_ME
1055 CopyMetaFilePict16to32( GlobalLock16(lpRender
->hData32
),
1056 GlobalLock(lpRender
->hData16
) );
1061 memcpy( GlobalLock(lpRender
->hData32
),
1062 GlobalLock16(lpRender
->hData16
),
1065 GlobalUnlock(lpRender
->hData32
);
1066 GlobalUnlock16(lpRender
->hData16
);
1069 TRACE("\treturning %04x (type %i)\n",
1070 lpRender
->hData32
, lpRender
->wFormatID
);
1071 return lpRender
->hData32
;
1075 /**************************************************************************
1076 * CountClipboardFormats (USER.143)
1078 INT16 WINAPI
CountClipboardFormats16(void)
1080 return CountClipboardFormats();
1084 /**************************************************************************
1085 * CountClipboardFormats (USER32.@)
1087 INT WINAPI
CountClipboardFormats(void)
1089 INT FormatCount
= 0;
1090 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
1096 if (lpFormat
== NULL
) break;
1098 if( lpFormat
->wFormatID
!= CF_TEXT
) /* Don't count CF_TEXT */
1101 * The format is available if either:
1102 * 1. The data is already in the cache.
1103 * 2. The selection is not owned by us(WINE) and the data is
1104 * available to the clipboard driver.
1106 if ( lpFormat
->wDataPresent
||
1107 ( !USER_Driver
.pIsSelectionOwner()
1108 && USER_Driver
.pIsClipboardFormatAvailable( lpFormat
->wFormatID
) ) )
1110 TRACE("\tdata found for format 0x%04x(%s)\n",
1111 lpFormat
->wFormatID
, CLIPBOARD_GetFormatName(lpFormat
->wFormatID
));
1116 lpFormat
= lpFormat
->NextFormat
;
1119 /* these are equivalent, adjust the total */
1120 FormatCount
+= (ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
||
1121 ClipFormats
[CF_TEXT
-1].wDataPresent
||
1122 ClipFormats
[CF_OEMTEXT
-1].wDataPresent
) ? 1 : 0;
1124 TRACE("\ttotal %d\n", FormatCount
);
1128 /**************************************************************************
1129 * EnumClipboardFormats (USER.144)
1131 UINT16 WINAPI
EnumClipboardFormats16( UINT16 wFormat
)
1133 return EnumClipboardFormats( wFormat
);
1137 /**************************************************************************
1138 * EnumClipboardFormats (USER32.@)
1140 UINT WINAPI
EnumClipboardFormats( UINT wFormat
)
1142 TRACE("(%04X)\n", wFormat
);
1144 if (CLIPBOARD_IsLocked())
1146 WARN("Clipboard not opened by calling task!\n");
1150 return CLIPBOARD_EnumClipboardFormats(wFormat
);
1154 /**************************************************************************
1155 * RegisterClipboardFormatA (USER32.@)
1157 UINT WINAPI
RegisterClipboardFormatA( LPCSTR FormatName
)
1159 LPWINE_CLIPFORMAT lpNewFormat
;
1160 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
1162 if (FormatName
== NULL
) return 0;
1164 TRACE("('%s') !\n", FormatName
);
1166 /* walk format chain to see if it's already registered */
1170 if ( !strcmp(lpFormat
->Name
,FormatName
) )
1172 lpFormat
->wRefCount
++;
1173 return lpFormat
->wFormatID
;
1176 if ( lpFormat
->NextFormat
== NULL
) break;
1178 lpFormat
= lpFormat
->NextFormat
;
1181 /* allocate storage for new format entry */
1183 lpNewFormat
= (LPWINE_CLIPFORMAT
)HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_CLIPFORMAT
));
1184 if(lpNewFormat
== NULL
) {
1185 WARN("No more memory for a new format!\n");
1188 lpFormat
->NextFormat
= lpNewFormat
;
1189 lpNewFormat
->wFormatID
= LastRegFormat
;
1190 lpNewFormat
->wRefCount
= 1;
1192 if (!(lpNewFormat
->Name
= HeapAlloc(GetProcessHeap(), 0, strlen(FormatName
)+1 )))
1194 WARN("No more memory for the new format name!\n");
1195 HeapFree(GetProcessHeap(), 0, lpNewFormat
);
1198 strcpy( lpNewFormat
->Name
, FormatName
);
1200 lpNewFormat
->wDataPresent
= 0;
1201 lpNewFormat
->hData16
= 0;
1202 lpNewFormat
->hDataSrc32
= 0;
1203 lpNewFormat
->hData32
= 0;
1204 lpNewFormat
->drvData
= 0;
1205 lpNewFormat
->PrevFormat
= lpFormat
;
1206 lpNewFormat
->NextFormat
= NULL
;
1208 /* Pass on the registration request to the driver */
1209 USER_Driver
.pRegisterClipboardFormat( FormatName
);
1211 return LastRegFormat
++;
1215 /**************************************************************************
1216 * RegisterClipboardFormat (USER.145)
1218 UINT16 WINAPI
RegisterClipboardFormat16( LPCSTR FormatName
)
1220 return RegisterClipboardFormatA( FormatName
);
1224 /**************************************************************************
1225 * RegisterClipboardFormatW (USER32.@)
1227 UINT WINAPI
RegisterClipboardFormatW( LPCWSTR formatName
)
1229 LPSTR aFormat
= HEAP_strdupWtoA( GetProcessHeap(), 0, formatName
);
1230 UINT ret
= RegisterClipboardFormatA( aFormat
);
1231 HeapFree( GetProcessHeap(), 0, aFormat
);
1236 /**************************************************************************
1237 * GetClipboardFormatName (USER.146)
1239 INT16 WINAPI
GetClipboardFormatName16( UINT16 wFormat
, LPSTR retStr
, INT16 maxlen
)
1241 return GetClipboardFormatNameA( wFormat
, retStr
, maxlen
);
1245 /**************************************************************************
1246 * GetClipboardFormatNameA (USER32.@)
1248 INT WINAPI
GetClipboardFormatNameA( UINT wFormat
, LPSTR retStr
, INT maxlen
)
1250 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
1252 TRACE("(%04X, %p, %d) !\n", wFormat
, retStr
, maxlen
);
1254 if (lpFormat
== NULL
|| lpFormat
->Name
== NULL
||
1255 lpFormat
->wFormatID
< CF_REGFORMATBASE
) return 0;
1257 TRACE("Name='%s' !\n", lpFormat
->Name
);
1259 lstrcpynA( retStr
, lpFormat
->Name
, maxlen
);
1260 return strlen(retStr
);
1264 /**************************************************************************
1265 * GetClipboardFormatNameW (USER32.@)
1267 INT WINAPI
GetClipboardFormatNameW( UINT wFormat
, LPWSTR retStr
, INT maxlen
)
1270 LPSTR p
= HeapAlloc( GetProcessHeap(), 0, maxlen
);
1271 if(p
== NULL
) return 0; /* FIXME: is this the correct failure value? */
1273 ret
= GetClipboardFormatNameA( wFormat
, p
, maxlen
);
1275 if (maxlen
> 0 && !MultiByteToWideChar( CP_ACP
, 0, p
, -1, retStr
, maxlen
))
1276 retStr
[maxlen
-1] = 0;
1277 HeapFree( GetProcessHeap(), 0, p
);
1282 /**************************************************************************
1283 * SetClipboardViewer (USER32.@)
1285 HWND WINAPI
SetClipboardViewer( HWND hWnd
)
1287 HWND hwndPrev
= hWndViewer
;
1289 TRACE("(%04x): returning %04x\n", hWnd
, hwndPrev
);
1291 hWndViewer
= WIN_GetFullHandle( hWnd
);
1296 /**************************************************************************
1297 * GetClipboardViewer (USER32.@)
1299 HWND WINAPI
GetClipboardViewer(void)
1306 /**************************************************************************
1307 * ChangeClipboardChain (USER32.@)
1309 BOOL WINAPI
ChangeClipboardChain(HWND hWnd
, HWND hWndNext
)
1313 FIXME("(0x%04x, 0x%04x): stub?\n", hWnd
, hWndNext
);
1316 bRet
= !SendMessageW( hWndViewer
, WM_CHANGECBCHAIN
, (WPARAM
)hWnd
, (LPARAM
)hWndNext
);
1318 WARN("hWndViewer is lost\n");
1320 if( WIN_GetFullHandle(hWnd
) == hWndViewer
) hWndViewer
= WIN_GetFullHandle( hWndNext
);
1326 /**************************************************************************
1327 * IsClipboardFormatAvailable (USER.193)
1329 BOOL16 WINAPI
IsClipboardFormatAvailable16( UINT16 wFormat
)
1331 return IsClipboardFormatAvailable( wFormat
);
1335 /**************************************************************************
1336 * IsClipboardFormatAvailable (USER32.@)
1338 BOOL WINAPI
IsClipboardFormatAvailable( UINT wFormat
)
1342 if (wFormat
== 0) /* Reject this case quickly */
1346 UINT iret
= CLIPBOARD_EnumClipboardFormats(wFormat
- 1);
1347 if ((wFormat
== CF_TEXT
) || (wFormat
== CF_OEMTEXT
) || (wFormat
== CF_UNICODETEXT
))
1348 bRet
= ((iret
== CF_TEXT
) || (iret
== CF_OEMTEXT
) || (iret
== CF_UNICODETEXT
));
1350 bRet
= iret
== wFormat
;
1352 TRACE("(%04X)- ret(%d)\n", wFormat
, bRet
);
1357 /**************************************************************************
1358 * GetOpenClipboardWindow (USER32.@)
1359 * FIXME: This wont work if an external app owns the selection
1361 HWND WINAPI
GetOpenClipboardWindow(void)
1364 return hWndClipWindow
;
1368 /**************************************************************************
1369 * GetPriorityClipboardFormat (USER32.@)
1371 INT WINAPI
GetPriorityClipboardFormat( UINT
*list
, INT nCount
)
1376 if(CountClipboardFormats() == 0) return 0;
1378 for (i
= 0; i
< nCount
; i
++)
1379 if (IsClipboardFormatAvailable( list
[i
] )) return list
[i
];
1384 /**************************************************************************
1385 * GetClipboardSequenceNumber (USER32.@)
1386 * Supported on Win2k/Win98
1387 * MSDN: Windows clipboard code keeps a serial number for the clipboard
1388 * for each window station. The number is incremented whenever the
1389 * contents change or are emptied.
1390 * If you do not have WINSTA_ACCESSCLIPBOARD then the function returns 0
1392 DWORD WINAPI
GetClipboardSequenceNumber(VOID
)
1394 FIXME("Returning 0, see windows/clipboard.c\n");
1395 /* FIXME: Use serial numbers */