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>
30 #include "wine/winuser16.h"
31 #include "wine/winbase16.h"
35 #include "clipboard.h"
36 #include "debugtools.h"
38 DEFAULT_DEBUG_CHANNEL(clipboard
);
40 #define CF_REGFORMATBASE 0xC000
42 /**************************************************************************
43 * Clipboard context global variables
46 static HANDLE hClipLock
= 0;
47 static BOOL bCBHasChanged
= FALSE
;
49 HWND hWndClipWindow
= 0; /* window that last opened clipboard */
50 HWND hWndClipOwner
= 0; /* current clipboard owner */
51 HANDLE16 hTaskClipOwner
= 0; /* clipboard owner's task */
52 static HWND hWndViewer
= 0; /* start of viewers chain */
54 static WORD LastRegFormat
= CF_REGFORMATBASE
;
56 /* Clipboard cache initial data.
57 * WARNING: This data ordering is dependent on the WINE_CLIPFORMAT structure
58 * declared in clipboard.h
60 WINE_CLIPFORMAT ClipFormats
[] = {
61 { CF_TEXT
, 1, 0, "Text", 0, 0, 0, 0, NULL
, &ClipFormats
[1]},
62 { CF_BITMAP
, 1, 0, "Bitmap", 0, 0, 0, 0, &ClipFormats
[0], &ClipFormats
[2]},
63 { CF_METAFILEPICT
, 1, 0, "MetaFile Picture", 0, 0, 0, 0, &ClipFormats
[1], &ClipFormats
[3]},
64 { CF_SYLK
, 1, 0, "Sylk", 0, 0, 0, 0, &ClipFormats
[2], &ClipFormats
[4]},
65 { CF_DIF
, 1, 0, "DIF", 0, 0, 0, 0, &ClipFormats
[3], &ClipFormats
[5]},
66 { CF_TIFF
, 1, 0, "TIFF", 0, 0, 0, 0, &ClipFormats
[4], &ClipFormats
[6]},
67 { CF_OEMTEXT
, 1, 0, "OEM Text", 0, 0, 0, 0, &ClipFormats
[5], &ClipFormats
[7]},
68 { CF_DIB
, 1, 0, "DIB", 0, 0, 0, 0, &ClipFormats
[6], &ClipFormats
[8]},
69 { CF_PALETTE
, 1, 0, "Palette", 0, 0, 0, 0, &ClipFormats
[7], &ClipFormats
[9]},
70 { CF_PENDATA
, 1, 0, "PenData", 0, 0, 0, 0, &ClipFormats
[8], &ClipFormats
[10]},
71 { CF_RIFF
, 1, 0, "RIFF", 0, 0, 0, 0, &ClipFormats
[9], &ClipFormats
[11]},
72 { CF_WAVE
, 1, 0, "Wave", 0, 0, 0, 0, &ClipFormats
[10], &ClipFormats
[12]},
73 { CF_UNICODETEXT
, 1, 0, "Unicode Text", 0, 0, 0, 0, &ClipFormats
[11], &ClipFormats
[13]},
74 { CF_OWNERDISPLAY
, 1, 0, "Owner Display", 0, 0, 0, 0, &ClipFormats
[12], &ClipFormats
[14]},
75 { CF_DSPTEXT
, 1, 0, "DSPText", 0, 0, 0, 0, &ClipFormats
[13], &ClipFormats
[15]},
76 { CF_DSPMETAFILEPICT
, 1, 0, "DSPMetaFile Picture", 0, 0, 0, 0, &ClipFormats
[14], &ClipFormats
[16]},
77 { CF_DSPBITMAP
, 1, 0, "DSPBitmap", 0, 0, 0, 0, &ClipFormats
[15], &ClipFormats
[17]},
78 { CF_HDROP
, 1, 0, "HDROP", 0, 0, 0, 0, &ClipFormats
[16], NULL
}
82 /**************************************************************************
83 * Internal Clipboard implementation methods
84 **************************************************************************/
87 /**************************************************************************
88 * CLIPBOARD_LookupFormat
90 static LPWINE_CLIPFORMAT
__lookup_format( LPWINE_CLIPFORMAT lpFormat
, WORD wID
)
94 if (lpFormat
== NULL
||
95 lpFormat
->wFormatID
== wID
) break;
96 lpFormat
= lpFormat
->NextFormat
;
101 LPWINE_CLIPFORMAT
CLIPBOARD_LookupFormat( WORD wID
)
103 return __lookup_format( ClipFormats
, wID
);
106 /**************************************************************************
108 * Check if the clipboard cache is available to the caller
110 BOOL
CLIPBOARD_IsLocked()
112 BOOL bIsLocked
= TRUE
;
113 HANDLE16 hTaskCur
= GetCurrentTask();
116 * The clipboard is available:
117 * 1. if the caller's task has opened the clipboard,
119 * 2. if the caller is the clipboard owners task, AND is responding to a
120 * WM_RENDERFORMAT message.
122 if ( hClipLock
== hTaskCur
)
125 else if ( hTaskCur
== hTaskClipOwner
)
127 /* Check if we're currently executing inside a window procedure
128 * called in response to a WM_RENDERFORMAT message. A WM_RENDERFORMAT
129 * handler is not permitted to open the clipboard since it has been opened
130 * by another client. However the handler must have access to the
131 * clipboard in order to update data in response to this message.
134 MESSAGEQUEUE
*queue
= QUEUE_Lock( GetFastQueue16() );
138 && queue
->smWaiting
->msg
== WM_RENDERFORMAT
139 && queue
->smWaiting
->hSrcQueue
143 QUEUE_Unlock( queue
);
145 /* FIXME: queue check no longer possible */
153 /**************************************************************************
154 * CLIPBOARD_ReleaseOwner
155 * Gives up ownership of the clipboard
157 void CLIPBOARD_ReleaseOwner()
163 /**************************************************************************
164 * CLIPBOARD_GlobalFreeProc
166 * This is a callback mechanism to allow HGLOBAL data to be released in
167 * the context of the process which allocated it. We post a WM_TIMER message
168 * to the owner window(in CLIPBOARD_DeleteRecord) and destroy the data(in idEvent)
169 * in this WndProc, which is invoked when the apps message loop calls DispatchMessage.
170 * This technique is discussed in Matt Pietrek's "Under the Hood".
171 * An article describing the same may be found in MSDN by searching for WM_TIMER.
172 * Note that this mechanism will probably stop working when WINE supports
173 * address space separation. When "queue events" are implemented in Wine we
174 * should switch to using that mechanism, since it is more robust and does not
175 * require a procedure address to be passed. See the SetWinEventHook API for
178 VOID CALLBACK
CLIPBOARD_GlobalFreeProc( HWND hwnd
, UINT uMsg
, UINT idEvent
, DWORD dwTime
)
180 /* idEvent is the HGLOBAL to be deleted */
181 GlobalFree( (HGLOBAL
)idEvent
);
184 /**************************************************************************
185 * CLIPBOARD_DeleteRecord
187 void CLIPBOARD_DeleteRecord(LPWINE_CLIPFORMAT lpFormat
, BOOL bChange
)
189 if( (lpFormat
->wFormatID
>= CF_GDIOBJFIRST
&&
190 lpFormat
->wFormatID
<= CF_GDIOBJLAST
) || lpFormat
->wFormatID
== CF_BITMAP
191 || lpFormat
->wFormatID
== CF_PALETTE
)
193 if (lpFormat
->hData32
)
194 DeleteObject(lpFormat
->hData32
);
195 if (lpFormat
->hData16
)
196 DeleteObject(lpFormat
->hData16
);
198 else if( lpFormat
->wFormatID
== CF_METAFILEPICT
)
200 if (lpFormat
->hData32
)
202 DeleteMetaFile( ((METAFILEPICT
*)GlobalLock( lpFormat
->hData32
))->hMF
);
203 PostMessageA(hWndClipOwner
, WM_TIMER
,
204 (WPARAM
)lpFormat
->hData32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
205 if (lpFormat
->hDataSrc32
)
207 /* Release lpFormat->hData32 in the context of the process which created it.
208 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
209 * GlobalFree(lpFormat->hDataSrc32);
211 PostMessageA(hWndClipOwner
, WM_TIMER
,
212 (WPARAM
)lpFormat
->hDataSrc32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
215 if (lpFormat
->hData16
)
216 /* HMETAFILE16 and HMETAFILE32 are apparently the same thing,
217 and a shallow copy is enough to share a METAFILEPICT
218 structure between 16bit and 32bit clipboards. The MetaFile
219 should of course only be deleted once. */
220 GlobalFree16(lpFormat
->hData16
);
222 if (lpFormat
->hData16
)
224 DeleteMetaFile16( ((METAFILEPICT16
*)GlobalLock16( lpFormat
->hData16
))->hMF
);
225 GlobalFree16(lpFormat
->hData16
);
230 if (lpFormat
->hData32
)
232 /* Release lpFormat->hData32 in the context of the process which created it.
233 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
234 * GlobalFree( lpFormat->hData32 );
236 PostMessageA(hWndClipOwner
, WM_TIMER
,
237 (WPARAM
)lpFormat
->hData32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
239 if (lpFormat
->hDataSrc32
)
241 /* Release lpFormat->hData32 in the context of the process which created it.
242 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
243 * GlobalFree(lpFormat->hDataSrc32);
245 PostMessageA(hWndClipOwner
, WM_TIMER
,
246 (WPARAM
)lpFormat
->hDataSrc32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
248 if (lpFormat
->hData16
)
249 GlobalFree16(lpFormat
->hData16
);
252 lpFormat
->wDataPresent
= 0;
253 lpFormat
->hData16
= 0;
254 lpFormat
->hData32
= 0;
255 lpFormat
->hDataSrc32
= 0;
256 lpFormat
->drvData
= 0;
258 if( bChange
) bCBHasChanged
= TRUE
;
261 /**************************************************************************
262 * CLIPBOARD_EmptyCache
264 void CLIPBOARD_EmptyCache( BOOL bChange
)
266 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
270 if ( lpFormat
->wDataPresent
|| lpFormat
->hData16
|| lpFormat
->hData32
)
271 CLIPBOARD_DeleteRecord( lpFormat
, bChange
);
273 lpFormat
= lpFormat
->NextFormat
;
277 /**************************************************************************
278 * CLIPBOARD_IsPresent
280 BOOL
CLIPBOARD_IsPresent(WORD wFormat
)
284 if( wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
|| wFormat
== CF_UNICODETEXT
)
285 return ClipFormats
[CF_TEXT
-1].wDataPresent
||
286 ClipFormats
[CF_OEMTEXT
-1].wDataPresent
||
287 ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
;
290 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
291 if( lpFormat
) return (lpFormat
->wDataPresent
);
296 /**************************************************************************
297 * CLIPBOARD_IsCacheRendered
298 * Checks if any data needs to be rendered to the clipboard cache
300 * TRUE - All clipboard data is available in the cache
301 * FALSE - Some data is marked for delayed render and needs rendering
303 BOOL
CLIPBOARD_IsCacheRendered()
305 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
307 /* check if all formats were rendered */
310 if( lpFormat
->wDataPresent
&& !lpFormat
->hData16
&& !lpFormat
->hData32
)
313 lpFormat
= lpFormat
->NextFormat
;
320 /**************************************************************************
321 * CLIPBOARD_IsMemoryObject
322 * Tests if the clipboard format specifies a memory object
324 BOOL
CLIPBOARD_IsMemoryObject( WORD wFormat
)
329 case CF_METAFILEPICT
:
341 /***********************************************************************
342 * CLIPBOARD_GlobalDupMem( HGLOBAL )
343 * Helper method to duplicate an HGLOBAL chunk of memory into shared memory
345 HGLOBAL
CLIPBOARD_GlobalDupMem( HGLOBAL hGlobalSrc
)
348 PVOID pGlobalSrc
, pGlobalDest
;
354 cBytes
= GlobalSize(hGlobalSrc
);
358 /* Turn on the DDESHARE and _MOVEABLE flags explicitly */
359 hGlobalDest
= GlobalAlloc( GlobalFlags(hGlobalSrc
) | GMEM_DDESHARE
| GMEM_MOVEABLE
,
364 pGlobalSrc
= GlobalLock(hGlobalSrc
);
365 pGlobalDest
= GlobalLock(hGlobalDest
);
366 if ( !pGlobalSrc
|| !pGlobalDest
)
369 memcpy(pGlobalDest
, pGlobalSrc
, cBytes
);
371 GlobalUnlock(hGlobalSrc
);
372 GlobalUnlock(hGlobalDest
);
377 /**************************************************************************
378 * CLIPBOARD_GetFormatName
379 * Gets the format name associated with an ID
381 char * CLIPBOARD_GetFormatName(UINT wFormat
)
383 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
384 return (lpFormat
) ? lpFormat
->Name
: NULL
;
388 /**************************************************************************
389 * CLIPBOARD_RenderFormat
391 static BOOL
CLIPBOARD_RenderFormat(LPWINE_CLIPFORMAT lpFormat
)
394 * If WINE is not the selection owner, and the format is available
395 * we must ask the driver to render the data to the clipboard cache.
397 TRACE("enter format=%d\n", lpFormat
->wFormatID
);
398 if ( !USER_Driver
.pIsSelectionOwner()
399 && USER_Driver
.pIsClipboardFormatAvailable( lpFormat
->wFormatID
) )
401 if ( !USER_Driver
.pGetClipboardData( lpFormat
->wFormatID
) )
405 * If Wine owns the clipboard, and the data is marked for delayed render,
408 else if( lpFormat
->wDataPresent
&& !lpFormat
->hData16
&& !lpFormat
->hData32
)
410 if( IsWindow(hWndClipOwner
) )
412 /* Send a WM_RENDERFORMAT message to notify the owner to render the
413 * data requested into the clipboard.
415 TRACE("Sending WM_RENDERFORMAT message\n");
416 SendMessage16(hWndClipOwner
,WM_RENDERFORMAT
,
417 (WPARAM16
)lpFormat
->wFormatID
,0L);
421 WARN("\thWndClipOwner (%04x) is lost!\n",
423 CLIPBOARD_ReleaseOwner();
424 lpFormat
->wDataPresent
= 0;
429 return (lpFormat
->hData16
|| lpFormat
->hData32
) ? TRUE
: FALSE
;
432 /**************************************************************************
433 * CLIPBOARD_ConvertText
434 * Returns number of required/converted characters - not bytes!
436 static INT
CLIPBOARD_ConvertText(WORD src_fmt
, void const *src
, INT src_size
,
437 WORD dst_fmt
, void *dst
, INT dst_size
)
441 if(src_fmt
== CF_UNICODETEXT
)
454 return WideCharToMultiByte(cp
, 0, src
, src_size
, dst
, dst_size
, NULL
, NULL
);
457 if(dst_fmt
== CF_UNICODETEXT
)
470 return MultiByteToWideChar(cp
, 0, src
, src_size
, dst
, dst_size
);
473 if(!dst_size
) return src_size
;
475 if(dst_size
> src_size
) dst_size
= src_size
;
477 if(src_fmt
== CF_TEXT
)
478 CharToOemBuffA(src
, dst
, dst_size
);
480 OemToCharBuffA(src
, dst
, dst_size
);
485 /**************************************************************************
486 * CLIPBOARD_RenderText
488 * Renders text to the clipboard buffer converting between UNIX and DOS formats.
490 * RETURNS: pointer to the WINE_CLIPFORMAT if successful, NULL otherwise
492 * FIXME: Should be a pair of driver functions that convert between OEM text and Windows.
495 static LPWINE_CLIPFORMAT
CLIPBOARD_RenderText( UINT wFormat
)
497 LPWINE_CLIPFORMAT lpSource
= ClipFormats
;
498 LPWINE_CLIPFORMAT lpTarget
= NULL
;
499 BOOL foundData
= FALSE
;
501 /* Asked for CF_TEXT */
502 if( wFormat
== CF_TEXT
)
504 if(ClipFormats
[CF_TEXT
-1].wDataPresent
)
506 lpSource
= &ClipFormats
[CF_TEXT
-1];
507 lpTarget
= &ClipFormats
[CF_TEXT
-1];
509 TRACE("\t TEXT -> TEXT\n");
511 else if(ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
)
513 /* Convert UNICODETEXT -> TEXT */
514 lpSource
= &ClipFormats
[CF_UNICODETEXT
-1];
515 lpTarget
= &ClipFormats
[CF_TEXT
-1];
517 TRACE("\tUNICODETEXT -> TEXT\n");
519 else if(ClipFormats
[CF_OEMTEXT
-1].wDataPresent
)
521 /* Convert OEMTEXT -> TEXT */
522 lpSource
= &ClipFormats
[CF_OEMTEXT
-1];
523 lpTarget
= &ClipFormats
[CF_TEXT
-1];
525 TRACE("\tOEMTEXT -> TEXT\n");
528 /* Asked for CF_OEMTEXT */
529 else if( wFormat
== CF_OEMTEXT
)
531 if(ClipFormats
[CF_OEMTEXT
-1].wDataPresent
)
533 lpSource
= &ClipFormats
[CF_OEMTEXT
-1];
534 lpTarget
= &ClipFormats
[CF_OEMTEXT
-1];
536 TRACE("\tOEMTEXT -> OEMTEXT\n");
538 else if(ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
)
540 /* Convert UNICODETEXT -> OEMTEXT */
541 lpSource
= &ClipFormats
[CF_UNICODETEXT
-1];
542 lpTarget
= &ClipFormats
[CF_OEMTEXT
-1];
544 TRACE("\tUNICODETEXT -> OEMTEXT\n");
546 else if(ClipFormats
[CF_TEXT
-1].wDataPresent
)
548 /* Convert TEXT -> OEMTEXT */
549 lpSource
= &ClipFormats
[CF_TEXT
-1];
550 lpTarget
= &ClipFormats
[CF_OEMTEXT
-1];
552 TRACE("\tTEXT -> OEMTEXT\n");
555 /* Asked for CF_UNICODETEXT */
556 else if( wFormat
== CF_UNICODETEXT
)
558 if(ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
)
560 lpSource
= &ClipFormats
[CF_UNICODETEXT
-1];
561 lpTarget
= &ClipFormats
[CF_UNICODETEXT
-1];
563 TRACE("\tUNICODETEXT -> UNICODETEXT\n");
565 else if(ClipFormats
[CF_TEXT
-1].wDataPresent
)
567 /* Convert TEXT -> UNICODETEXT */
568 lpSource
= &ClipFormats
[CF_TEXT
-1];
569 lpTarget
= &ClipFormats
[CF_UNICODETEXT
-1];
571 TRACE("\tTEXT -> UNICODETEXT\n");
573 else if(ClipFormats
[CF_OEMTEXT
-1].wDataPresent
)
575 /* Convert OEMTEXT -> UNICODETEXT */
576 lpSource
= &ClipFormats
[CF_OEMTEXT
-1];
577 lpTarget
= &ClipFormats
[CF_UNICODETEXT
-1];
579 TRACE("\tOEMTEXT -> UNICODETEXT\n");
584 if ((wFormat
== CF_TEXT
) || (wFormat
== CF_OEMTEXT
))
586 lpSource
= &ClipFormats
[CF_UNICODETEXT
-1];
587 lpTarget
= __lookup_format( ClipFormats
, wFormat
);
591 lpSource
= __lookup_format( ClipFormats
, wFormat
);
596 /* First render the source text format */
597 if ( !lpSource
|| !CLIPBOARD_RenderFormat(lpSource
) ) return NULL
;
599 /* Convert to the desired target text format, if necessary */
600 if( lpTarget
!= lpSource
&& !lpTarget
->hData16
&& !lpTarget
->hData32
)
602 INT src_chars
, dst_chars
, alloc_size
;
606 if (lpSource
->hData32
)
608 lpstrS
= (LPSTR
)GlobalLock(lpSource
->hData32
);
612 lpstrS
= (LPSTR
)GlobalLock16(lpSource
->hData16
);
615 if( !lpstrS
) return NULL
;
617 /* Text always NULL terminated */
618 if(lpSource
->wFormatID
== CF_UNICODETEXT
)
619 src_chars
= strlenW((LPCWSTR
)lpstrS
)+1;
621 src_chars
= strlen(lpstrS
)+1;
623 /* Calculate number of characters in the destination buffer */
624 dst_chars
= CLIPBOARD_ConvertText(lpSource
->wFormatID
, lpstrS
, src_chars
,
625 lpTarget
->wFormatID
, NULL
, 0);
626 if(!dst_chars
) return NULL
;
628 TRACE("\tconverting from '%s' to '%s', %i chars\n",
629 lpSource
->Name
, lpTarget
->Name
, src_chars
);
631 /* Convert characters to bytes */
632 if(lpTarget
->wFormatID
== CF_UNICODETEXT
)
633 alloc_size
= dst_chars
* sizeof(WCHAR
);
635 alloc_size
= dst_chars
;
637 lpTarget
->hData32
= GlobalAlloc(GMEM_ZEROINIT
| GMEM_MOVEABLE
| GMEM_DDESHARE
, alloc_size
);
638 lpstrT
= (LPSTR
)GlobalLock(lpTarget
->hData32
);
642 CLIPBOARD_ConvertText(lpSource
->wFormatID
, lpstrS
, src_chars
,
643 lpTarget
->wFormatID
, lpstrT
, dst_chars
);
644 GlobalUnlock(lpTarget
->hData32
);
647 lpTarget
->hData32
= 0;
650 if (lpSource
->hData32
)
651 GlobalUnlock(lpSource
->hData32
);
653 GlobalUnlock16(lpSource
->hData16
);
656 return (lpTarget
->hData16
|| lpTarget
->hData32
) ? lpTarget
: NULL
;
659 /**************************************************************************
660 * CLIPBOARD_EnumClipboardFormats (internal)
662 static UINT
CLIPBOARD_EnumClipboardFormats( UINT wFormat
)
664 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
667 if (wFormat
== 0) /* start from the beginning */
668 lpFormat
= ClipFormats
;
671 /* walk up to the specified format record */
673 if( !(lpFormat
= __lookup_format( lpFormat
, wFormat
)) )
675 lpFormat
= lpFormat
->NextFormat
; /* right */
680 if (lpFormat
== NULL
) return 0;
682 if(CLIPBOARD_IsPresent(lpFormat
->wFormatID
))
685 /* Query the driver if not yet in the cache */
686 if (!USER_Driver
.pIsSelectionOwner())
688 if(lpFormat
->wFormatID
== CF_UNICODETEXT
||
689 lpFormat
->wFormatID
== CF_TEXT
||
690 lpFormat
->wFormatID
== CF_OEMTEXT
)
692 if(USER_Driver
.pIsClipboardFormatAvailable(CF_UNICODETEXT
) ||
693 USER_Driver
.pIsClipboardFormatAvailable(CF_TEXT
) ||
694 USER_Driver
.pIsClipboardFormatAvailable(CF_OEMTEXT
))
695 bFormatPresent
= TRUE
;
697 bFormatPresent
= FALSE
;
700 bFormatPresent
= USER_Driver
.pIsClipboardFormatAvailable(lpFormat
->wFormatID
);
706 lpFormat
= lpFormat
->NextFormat
;
709 TRACE("Next available format %d\n", lpFormat
->wFormatID
);
711 return lpFormat
->wFormatID
;
715 /**************************************************************************
716 * WIN32 Clipboard implementation
717 **************************************************************************/
719 /**************************************************************************
720 * OpenClipboard (USER.137)
722 BOOL16 WINAPI
OpenClipboard16( HWND16 hWnd
)
724 return OpenClipboard( hWnd
);
728 /**************************************************************************
729 * OpenClipboard (USER32.@)
731 * Note: Netscape uses NULL hWnd to open the clipboard.
733 BOOL WINAPI
OpenClipboard( HWND hWnd
)
737 TRACE("(%04x)...\n", hWnd
);
741 hClipLock
= GetCurrentTask();
743 /* Save current user of the clipboard */
744 hWndClipWindow
= hWnd
;
745 bCBHasChanged
= FALSE
;
750 TRACE(" returning %i\n", bRet
);
755 /**************************************************************************
756 * CloseClipboard (USER.138)
758 BOOL16 WINAPI
CloseClipboard16(void)
760 return CloseClipboard();
764 /**************************************************************************
765 * CloseClipboard (USER32.@)
767 BOOL WINAPI
CloseClipboard(void)
771 if (hClipLock
== GetCurrentTask())
775 if (bCBHasChanged
&& hWndViewer
)
776 SendMessage16(hWndViewer
, WM_DRAWCLIPBOARD
, 0, 0L);
783 /**************************************************************************
784 * EmptyClipboard (USER.139)
786 BOOL16 WINAPI
EmptyClipboard16(void)
788 return EmptyClipboard();
792 /**************************************************************************
793 * EmptyClipboard (USER32.@)
794 * Empties and acquires ownership of the clipboard
796 BOOL WINAPI
EmptyClipboard(void)
800 if (hClipLock
!= GetCurrentTask())
802 WARN("Clipboard not opened by calling task!\n");
806 /* destroy private objects */
809 SendMessage16(hWndClipOwner
, WM_DESTROYCLIPBOARD
, 0, 0L);
811 /* empty the cache */
812 CLIPBOARD_EmptyCache(TRUE
);
814 /* Assign ownership of the clipboard to the current client */
815 hWndClipOwner
= hWndClipWindow
;
817 /* Save the current task */
818 hTaskClipOwner
= GetCurrentTask();
820 /* Tell the driver to acquire the selection */
821 USER_Driver
.pAcquireClipboard();
827 /**************************************************************************
828 * GetClipboardOwner (USER.140)
829 * FIXME: Can't return the owner if the clipbard is owned by an external app
831 HWND16 WINAPI
GetClipboardOwner16(void)
834 return hWndClipOwner
;
838 /**************************************************************************
839 * GetClipboardOwner (USER32.@)
840 * FIXME: Can't return the owner if the clipbard is owned by an external app
842 HWND WINAPI
GetClipboardOwner(void)
845 return hWndClipOwner
;
849 /**************************************************************************
850 * SetClipboardData (USER.141)
852 HANDLE16 WINAPI
SetClipboardData16( UINT16 wFormat
, HANDLE16 hData
)
854 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
856 TRACE("(%04X, %04x) !\n", wFormat
, hData
);
858 /* NOTE: If the hData is zero and current owner doesn't match
859 * the window that opened the clipboard then this application
860 * is screwed because WM_RENDERFORMAT will go to the owner.
861 * (to become the owner it must call EmptyClipboard() before
865 if( CLIPBOARD_IsLocked() || !lpFormat
||
866 (!hData
&& (!hWndClipOwner
|| (hWndClipOwner
!= hWndClipWindow
))) )
868 WARN("Invalid hData or clipboard not opened by calling task!\n");
872 /* Pass on the request to the driver */
873 USER_Driver
.pSetClipboardData(wFormat
);
875 if ( lpFormat
->wDataPresent
|| lpFormat
->hData16
|| lpFormat
->hData32
)
877 CLIPBOARD_DeleteRecord(lpFormat
, TRUE
);
879 /* delete existing CF_UNICODETEXT/CF_TEXT/CF_OEMTEXT aliases */
880 if(wFormat
== CF_UNICODETEXT
)
882 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
883 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
885 else if(wFormat
== CF_TEXT
)
887 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_UNICODETEXT
-1], TRUE
);
888 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
890 else if(wFormat
== CF_OEMTEXT
)
892 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_UNICODETEXT
-1], TRUE
);
893 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
897 bCBHasChanged
= TRUE
;
898 lpFormat
->wDataPresent
= 1;
899 lpFormat
->hData16
= hData
; /* 0 is legal, see WM_RENDERFORMAT */
900 lpFormat
->hData32
= 0;
902 return lpFormat
->hData16
;
906 /**************************************************************************
907 * SetClipboardData (USER32.@)
909 HANDLE WINAPI
SetClipboardData( UINT wFormat
, HANDLE hData
)
911 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
913 TRACE("(%08X, %08x) !\n", wFormat
, hData
);
915 /* NOTE: If the hData is zero and current owner doesn't match
916 * the window that opened the clipboard then this application
917 * is screwed because WM_RENDERFORMAT will go to the owner.
918 * (to become the owner it must call EmptyClipboard() before
922 if( CLIPBOARD_IsLocked() || !lpFormat
||
923 (!hData
&& (!hWndClipOwner
|| (hWndClipOwner
!= hWndClipWindow
))) )
925 WARN("Invalid hData or clipboard not opened by calling task!\n");
929 /* Tell the driver to acquire the selection */
930 USER_Driver
.pAcquireClipboard();
932 if ( lpFormat
->wDataPresent
&&
933 (lpFormat
->hData16
|| lpFormat
->hData32
) )
935 CLIPBOARD_DeleteRecord(lpFormat
, TRUE
);
937 /* delete existing CF_UNICODETEXT/CF_TEXT/CF_OEMTEXT aliases */
938 if(wFormat
== CF_UNICODETEXT
)
940 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
941 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
943 else if(wFormat
== CF_TEXT
)
945 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_UNICODETEXT
-1], TRUE
);
946 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
948 else if(wFormat
== CF_OEMTEXT
)
950 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_UNICODETEXT
-1], TRUE
);
951 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
955 bCBHasChanged
= TRUE
;
956 lpFormat
->wDataPresent
= 1;
957 lpFormat
->hDataSrc32
= hData
; /* Save the source handle */
960 * Make a shared duplicate if the memory is not shared
961 * TODO: What should be done for non-memory objects
963 if ( CLIPBOARD_IsMemoryObject(wFormat
) && hData
&& !(GlobalFlags(hData
) & GMEM_DDESHARE
) )
964 lpFormat
->hData32
= CLIPBOARD_GlobalDupMem( hData
);
966 lpFormat
->hData32
= hData
; /* 0 is legal, see WM_RENDERFORMAT */
968 lpFormat
->hData16
= 0;
970 return lpFormat
->hData32
; /* Should we return lpFormat->hDataSrc32 */
974 /**************************************************************************
975 * GetClipboardData (USER.142)
977 HANDLE16 WINAPI
GetClipboardData16( UINT16 wFormat
)
979 LPWINE_CLIPFORMAT lpRender
= ClipFormats
;
981 TRACE("(%04X)\n", wFormat
);
983 if (CLIPBOARD_IsLocked())
985 WARN("Clipboard not opened by calling task!\n");
989 if( wFormat
== CF_UNICODETEXT
|| wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
)
991 lpRender
= CLIPBOARD_RenderText(wFormat
);
992 if ( !lpRender
) return 0;
996 lpRender
= __lookup_format( ClipFormats
, wFormat
);
997 if( !lpRender
|| !CLIPBOARD_RenderFormat(lpRender
) ) return 0;
1000 /* Convert between 32 -> 16 bit data, if necessary */
1001 if( lpRender
->hData32
&& !lpRender
->hData16
1002 && CLIPBOARD_IsMemoryObject(wFormat
) )
1005 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
1006 size
= sizeof( METAFILEPICT16
);
1008 size
= GlobalSize(lpRender
->hData32
);
1010 lpRender
->hData16
= GlobalAlloc16(GMEM_ZEROINIT
, size
);
1011 if( !lpRender
->hData16
)
1012 ERR("(%04X) -- not enough memory in 16b heap\n", wFormat
);
1015 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
1017 FIXME("\timplement function CopyMetaFilePict32to16\n");
1018 FIXME("\tin the appropriate file.\n");
1019 #ifdef SOMEONE_IMPLEMENTED_ME
1020 CopyMetaFilePict32to16( GlobalLock16(lpRender
->hData16
),
1021 GlobalLock(lpRender
->hData32
) );
1026 memcpy( GlobalLock16(lpRender
->hData16
),
1027 GlobalLock(lpRender
->hData32
),
1030 GlobalUnlock16(lpRender
->hData16
);
1031 GlobalUnlock(lpRender
->hData32
);
1035 TRACE("\treturning %04x (type %i)\n",
1036 lpRender
->hData16
, lpRender
->wFormatID
);
1037 return lpRender
->hData16
;
1041 /**************************************************************************
1042 * GetClipboardData (USER32.@)
1044 HANDLE WINAPI
GetClipboardData( UINT wFormat
)
1046 LPWINE_CLIPFORMAT lpRender
= ClipFormats
;
1048 TRACE("(%08X)\n", wFormat
);
1050 if (CLIPBOARD_IsLocked())
1052 WARN("Clipboard not opened by calling task!\n");
1056 if( wFormat
== CF_UNICODETEXT
|| wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
)
1058 lpRender
= CLIPBOARD_RenderText(wFormat
);
1059 if ( !lpRender
) return 0;
1063 lpRender
= __lookup_format( ClipFormats
, wFormat
);
1064 if( !lpRender
|| !CLIPBOARD_RenderFormat(lpRender
) ) return 0;
1067 /* Convert between 16 -> 32 bit data, if necessary */
1068 if( lpRender
->hData16
&& !lpRender
->hData32
1069 && CLIPBOARD_IsMemoryObject(wFormat
) )
1072 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
1073 size
= sizeof( METAFILEPICT
);
1075 size
= GlobalSize16(lpRender
->hData16
);
1076 lpRender
->hData32
= GlobalAlloc(GMEM_ZEROINIT
| GMEM_MOVEABLE
| GMEM_DDESHARE
,
1078 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
1080 FIXME("\timplement function CopyMetaFilePict16to32\n");
1081 FIXME("\tin the appropriate file.\n");
1082 #ifdef SOMEONE_IMPLEMENTED_ME
1083 CopyMetaFilePict16to32( GlobalLock16(lpRender
->hData32
),
1084 GlobalLock(lpRender
->hData16
) );
1089 memcpy( GlobalLock(lpRender
->hData32
),
1090 GlobalLock16(lpRender
->hData16
),
1093 GlobalUnlock(lpRender
->hData32
);
1094 GlobalUnlock16(lpRender
->hData16
);
1097 TRACE("\treturning %04x (type %i)\n",
1098 lpRender
->hData32
, lpRender
->wFormatID
);
1099 return lpRender
->hData32
;
1103 /**************************************************************************
1104 * CountClipboardFormats (USER.143)
1106 INT16 WINAPI
CountClipboardFormats16(void)
1108 return CountClipboardFormats();
1112 /**************************************************************************
1113 * CountClipboardFormats (USER32.@)
1115 INT WINAPI
CountClipboardFormats(void)
1117 INT FormatCount
= 0;
1118 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
1124 if (lpFormat
== NULL
) break;
1126 if( lpFormat
->wFormatID
!= CF_TEXT
) /* Don't count CF_TEXT */
1129 * The format is available if either:
1130 * 1. The data is already in the cache.
1131 * 2. The selection is not owned by us(WINE) and the data is
1132 * available to the clipboard driver.
1134 if ( lpFormat
->wDataPresent
||
1135 ( !USER_Driver
.pIsSelectionOwner()
1136 && USER_Driver
.pIsClipboardFormatAvailable( lpFormat
->wFormatID
) ) )
1138 TRACE("\tdata found for format 0x%04x(%s)\n",
1139 lpFormat
->wFormatID
, CLIPBOARD_GetFormatName(lpFormat
->wFormatID
));
1144 lpFormat
= lpFormat
->NextFormat
;
1147 /* these are equivalent, adjust the total */
1148 FormatCount
+= (ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
||
1149 ClipFormats
[CF_TEXT
-1].wDataPresent
||
1150 ClipFormats
[CF_OEMTEXT
-1].wDataPresent
) ? 1 : 0;
1152 TRACE("\ttotal %d\n", FormatCount
);
1156 /**************************************************************************
1157 * EnumClipboardFormats (USER.144)
1159 UINT16 WINAPI
EnumClipboardFormats16( UINT16 wFormat
)
1161 return EnumClipboardFormats( wFormat
);
1165 /**************************************************************************
1166 * EnumClipboardFormats (USER32.@)
1168 UINT WINAPI
EnumClipboardFormats( UINT wFormat
)
1170 TRACE("(%04X)\n", wFormat
);
1172 if (CLIPBOARD_IsLocked())
1174 WARN("Clipboard not opened by calling task!\n");
1178 return CLIPBOARD_EnumClipboardFormats(wFormat
);
1182 /**************************************************************************
1183 * RegisterClipboardFormatA (USER32.@)
1185 UINT WINAPI
RegisterClipboardFormatA( LPCSTR FormatName
)
1187 LPWINE_CLIPFORMAT lpNewFormat
;
1188 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
1190 if (FormatName
== NULL
) return 0;
1192 TRACE("('%s') !\n", FormatName
);
1194 /* walk format chain to see if it's already registered */
1198 if ( !strcmp(lpFormat
->Name
,FormatName
) )
1200 lpFormat
->wRefCount
++;
1201 return lpFormat
->wFormatID
;
1204 if ( lpFormat
->NextFormat
== NULL
) break;
1206 lpFormat
= lpFormat
->NextFormat
;
1209 /* allocate storage for new format entry */
1211 lpNewFormat
= (LPWINE_CLIPFORMAT
)HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_CLIPFORMAT
));
1212 if(lpNewFormat
== NULL
) {
1213 WARN("No more memory for a new format!\n");
1216 lpFormat
->NextFormat
= lpNewFormat
;
1217 lpNewFormat
->wFormatID
= LastRegFormat
;
1218 lpNewFormat
->wRefCount
= 1;
1220 lpNewFormat
->Name
= (LPSTR
)HEAP_strdupA(GetProcessHeap(), 0, FormatName
);
1221 if(lpNewFormat
->Name
== NULL
) {
1222 WARN("No more memory for the new format name!\n");
1223 HeapFree(GetProcessHeap(), 0, lpNewFormat
);
1227 lpNewFormat
->wDataPresent
= 0;
1228 lpNewFormat
->hData16
= 0;
1229 lpNewFormat
->hDataSrc32
= 0;
1230 lpNewFormat
->hData32
= 0;
1231 lpNewFormat
->drvData
= 0;
1232 lpNewFormat
->PrevFormat
= lpFormat
;
1233 lpNewFormat
->NextFormat
= NULL
;
1235 /* Pass on the registration request to the driver */
1236 USER_Driver
.pRegisterClipboardFormat( FormatName
);
1238 return LastRegFormat
++;
1242 /**************************************************************************
1243 * RegisterClipboardFormat (USER.145)
1245 UINT16 WINAPI
RegisterClipboardFormat16( LPCSTR FormatName
)
1247 return RegisterClipboardFormatA( FormatName
);
1251 /**************************************************************************
1252 * RegisterClipboardFormatW (USER32.@)
1254 UINT WINAPI
RegisterClipboardFormatW( LPCWSTR formatName
)
1256 LPSTR aFormat
= HEAP_strdupWtoA( GetProcessHeap(), 0, formatName
);
1257 UINT ret
= RegisterClipboardFormatA( aFormat
);
1258 HeapFree( GetProcessHeap(), 0, aFormat
);
1263 /**************************************************************************
1264 * GetClipboardFormatName (USER.146)
1266 INT16 WINAPI
GetClipboardFormatName16( UINT16 wFormat
, LPSTR retStr
, INT16 maxlen
)
1268 return GetClipboardFormatNameA( wFormat
, retStr
, maxlen
);
1272 /**************************************************************************
1273 * GetClipboardFormatNameA (USER32.@)
1275 INT WINAPI
GetClipboardFormatNameA( UINT wFormat
, LPSTR retStr
, INT maxlen
)
1277 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
1279 TRACE("(%04X, %p, %d) !\n", wFormat
, retStr
, maxlen
);
1281 if (lpFormat
== NULL
|| lpFormat
->Name
== NULL
||
1282 lpFormat
->wFormatID
< CF_REGFORMATBASE
) return 0;
1284 TRACE("Name='%s' !\n", lpFormat
->Name
);
1286 lstrcpynA( retStr
, lpFormat
->Name
, maxlen
);
1287 return strlen(retStr
);
1291 /**************************************************************************
1292 * GetClipboardFormatNameW (USER32.@)
1294 INT WINAPI
GetClipboardFormatNameW( UINT wFormat
, LPWSTR retStr
, INT maxlen
)
1297 LPSTR p
= HeapAlloc( GetProcessHeap(), 0, maxlen
);
1298 if(p
== NULL
) return 0; /* FIXME: is this the correct failure value? */
1300 ret
= GetClipboardFormatNameA( wFormat
, p
, maxlen
);
1302 if (maxlen
> 0 && !MultiByteToWideChar( CP_ACP
, 0, p
, -1, retStr
, maxlen
))
1303 retStr
[maxlen
-1] = 0;
1304 HeapFree( GetProcessHeap(), 0, p
);
1309 /**************************************************************************
1310 * SetClipboardViewer (USER.147)
1312 HWND16 WINAPI
SetClipboardViewer16( HWND16 hWnd
)
1314 TRACE("(%04x)\n", hWnd
);
1315 return SetClipboardViewer( hWnd
);
1319 /**************************************************************************
1320 * SetClipboardViewer (USER32.@)
1322 HWND WINAPI
SetClipboardViewer( HWND hWnd
)
1324 HWND hwndPrev
= hWndViewer
;
1326 TRACE("(%04x): returning %04x\n", hWnd
, hwndPrev
);
1333 /**************************************************************************
1334 * GetClipboardViewer (USER.148)
1336 HWND16 WINAPI
GetClipboardViewer16(void)
1343 /**************************************************************************
1344 * GetClipboardViewer (USER32.@)
1346 HWND WINAPI
GetClipboardViewer(void)
1353 /**************************************************************************
1354 * ChangeClipboardChain (USER.149)
1356 BOOL16 WINAPI
ChangeClipboardChain16(HWND16 hWnd
, HWND16 hWndNext
)
1358 return ChangeClipboardChain(hWnd
, hWndNext
);
1362 /**************************************************************************
1363 * ChangeClipboardChain (USER32.@)
1365 BOOL WINAPI
ChangeClipboardChain(HWND hWnd
, HWND hWndNext
)
1369 FIXME("(0x%04x, 0x%04x): stub?\n", hWnd
, hWndNext
);
1372 bRet
= !SendMessage16( hWndViewer
, WM_CHANGECBCHAIN
,
1373 (WPARAM16
)hWnd
, (LPARAM
)hWndNext
);
1375 WARN("hWndViewer is lost\n");
1377 if( hWnd
== hWndViewer
) hWndViewer
= hWndNext
;
1383 /**************************************************************************
1384 * IsClipboardFormatAvailable (USER.193)
1386 BOOL16 WINAPI
IsClipboardFormatAvailable16( UINT16 wFormat
)
1388 return IsClipboardFormatAvailable( wFormat
);
1392 /**************************************************************************
1393 * IsClipboardFormatAvailable (USER32.@)
1395 BOOL WINAPI
IsClipboardFormatAvailable( UINT wFormat
)
1399 if (wFormat
== 0) /* Reject this case quickly */
1403 UINT iret
= CLIPBOARD_EnumClipboardFormats(wFormat
- 1);
1404 if ((wFormat
== CF_TEXT
) || (wFormat
== CF_OEMTEXT
) || (wFormat
== CF_UNICODETEXT
))
1405 bRet
= ((iret
== CF_TEXT
) || (iret
== CF_OEMTEXT
) || (iret
== CF_UNICODETEXT
));
1407 bRet
= iret
== wFormat
;
1409 TRACE("(%04X)- ret(%d)\n", wFormat
, bRet
);
1414 /**************************************************************************
1415 * GetOpenClipboardWindow (USER.248)
1416 * FIXME: This wont work if an external app owns the selection
1418 HWND16 WINAPI
GetOpenClipboardWindow16(void)
1421 return hWndClipWindow
;
1425 /**************************************************************************
1426 * GetOpenClipboardWindow (USER32.@)
1427 * FIXME: This wont work if an external app owns the selection
1429 HWND WINAPI
GetOpenClipboardWindow(void)
1432 return hWndClipWindow
;
1436 /**************************************************************************
1437 * GetPriorityClipboardFormat (USER.402)
1439 INT16 WINAPI
GetPriorityClipboardFormat16( UINT16
*lpPriorityList
, INT16 nCount
)
1441 FIXME("(%p,%d): stub\n", lpPriorityList
, nCount
);
1446 /**************************************************************************
1447 * GetPriorityClipboardFormat (USER32.@)
1449 INT WINAPI
GetPriorityClipboardFormat( UINT
*lpPriorityList
, INT nCount
)
1454 if(CountClipboardFormats() == 0)
1459 for(Counter
= 0; Counter
<= nCount
; Counter
++)
1461 if(IsClipboardFormatAvailable(*(lpPriorityList
+sizeof(INT
)*Counter
)))
1462 return *(lpPriorityList
+sizeof(INT
)*Counter
);
1469 /**************************************************************************
1470 * GetClipboardSequenceNumber (USER32.@)
1471 * Supported on Win2k/Win98
1472 * MSDN: Windows clipboard code keeps a serial number for the clipboard
1473 * for each window station. The number is incremented whenever the
1474 * contents change or are emptied.
1475 * If you do not have WINSTA_ACCESSCLIPBOARD then the function returns 0
1477 DWORD WINAPI
GetClipboardSequenceNumber(VOID
)
1479 FIXME("Returning 0, see windows/clipboard.c\n");
1480 /* FIXME: Use serial numbers */