2 * WIN32 clipboard implementation
4 * Copyright 1994 Martin Ayotte
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * This file contains the implementation for the WIN32 Clipboard API
24 * and Wine's internal clipboard cache.
25 * The actual contents of the clipboard are held in the clipboard cache.
26 * The internal implementation talks to a "clipboard driver" to fill or
27 * expose the cache to the native device. (Currently only the X11 and
28 * TTY clipboard driver are available)
34 #include <sys/types.h>
45 #include "wine/winuser16.h"
46 #include "wine/winbase16.h"
50 #include "clipboard.h"
51 #include "wine/debug.h"
53 WINE_DEFAULT_DEBUG_CHANNEL(clipboard
);
55 #define CF_REGFORMATBASE 0xC000
57 /**************************************************************************
58 * Clipboard context global variables
61 static HANDLE hClipLock
= 0;
62 static BOOL bCBHasChanged
= FALSE
;
64 static HWND hWndClipWindow
; /* window that last opened clipboard */
65 static HWND hWndClipOwner
; /* current clipboard owner */
66 static HANDLE16 hTaskClipOwner
; /* clipboard owner's task */
67 static HWND hWndViewer
; /* start of viewers chain */
69 static WORD LastRegFormat
= CF_REGFORMATBASE
;
71 /* Clipboard cache initial data.
72 * WARNING: This data ordering is dependent on the WINE_CLIPFORMAT structure
73 * declared in clipboard.h
75 WINE_CLIPFORMAT ClipFormats
[] = {
76 { CF_TEXT
, 1, 0, "Text", 0, 0, 0, 0, NULL
, &ClipFormats
[1]},
77 { CF_BITMAP
, 1, 0, "Bitmap", 0, 0, 0, 0, &ClipFormats
[0], &ClipFormats
[2]},
78 { CF_METAFILEPICT
, 1, 0, "MetaFile Picture", 0, 0, 0, 0, &ClipFormats
[1], &ClipFormats
[3]},
79 { CF_SYLK
, 1, 0, "Sylk", 0, 0, 0, 0, &ClipFormats
[2], &ClipFormats
[4]},
80 { CF_DIF
, 1, 0, "DIF", 0, 0, 0, 0, &ClipFormats
[3], &ClipFormats
[5]},
81 { CF_TIFF
, 1, 0, "TIFF", 0, 0, 0, 0, &ClipFormats
[4], &ClipFormats
[6]},
82 { CF_OEMTEXT
, 1, 0, "OEM Text", 0, 0, 0, 0, &ClipFormats
[5], &ClipFormats
[7]},
83 { CF_DIB
, 1, 0, "DIB", 0, 0, 0, 0, &ClipFormats
[6], &ClipFormats
[8]},
84 { CF_PALETTE
, 1, 0, "Palette", 0, 0, 0, 0, &ClipFormats
[7], &ClipFormats
[9]},
85 { CF_PENDATA
, 1, 0, "PenData", 0, 0, 0, 0, &ClipFormats
[8], &ClipFormats
[10]},
86 { CF_RIFF
, 1, 0, "RIFF", 0, 0, 0, 0, &ClipFormats
[9], &ClipFormats
[11]},
87 { CF_WAVE
, 1, 0, "Wave", 0, 0, 0, 0, &ClipFormats
[10], &ClipFormats
[12]},
88 { CF_UNICODETEXT
, 1, 0, "Unicode Text", 0, 0, 0, 0, &ClipFormats
[11], &ClipFormats
[13]},
89 { CF_OWNERDISPLAY
, 1, 0, "Owner Display", 0, 0, 0, 0, &ClipFormats
[12], &ClipFormats
[14]},
90 { CF_DSPTEXT
, 1, 0, "DSPText", 0, 0, 0, 0, &ClipFormats
[13], &ClipFormats
[15]},
91 { CF_DSPMETAFILEPICT
, 1, 0, "DSPMetaFile Picture", 0, 0, 0, 0, &ClipFormats
[14], &ClipFormats
[16]},
92 { CF_DSPBITMAP
, 1, 0, "DSPBitmap", 0, 0, 0, 0, &ClipFormats
[15], &ClipFormats
[17]},
93 { CF_HDROP
, 1, 0, "HDROP", 0, 0, 0, 0, &ClipFormats
[16], NULL
}
97 /**************************************************************************
98 * Internal Clipboard implementation methods
99 **************************************************************************/
102 /**************************************************************************
103 * CLIPBOARD_LookupFormat
105 static LPWINE_CLIPFORMAT
__lookup_format( LPWINE_CLIPFORMAT lpFormat
, WORD wID
)
109 if (lpFormat
== NULL
||
110 lpFormat
->wFormatID
== wID
) break;
111 lpFormat
= lpFormat
->NextFormat
;
116 LPWINE_CLIPFORMAT
CLIPBOARD_LookupFormat( WORD wID
)
118 return __lookup_format( ClipFormats
, wID
);
121 /**************************************************************************
123 * Check if the clipboard cache is available to the caller
125 BOOL
CLIPBOARD_IsLocked()
127 BOOL bIsLocked
= TRUE
;
128 HANDLE16 hTaskCur
= GetCurrentTask();
131 * The clipboard is available:
132 * 1. if the caller's task has opened the clipboard,
134 * 2. if the caller is the clipboard owners task, AND is responding to a
135 * WM_RENDERFORMAT message.
137 if ( hClipLock
== hTaskCur
)
140 else if ( hTaskCur
== hTaskClipOwner
)
142 /* Check if we're currently executing inside a window procedure
143 * called in response to a WM_RENDERFORMAT message. A WM_RENDERFORMAT
144 * handler is not permitted to open the clipboard since it has been opened
145 * by another client. However the handler must have access to the
146 * clipboard in order to update data in response to this message.
149 MESSAGEQUEUE
*queue
= QUEUE_Current();
153 && queue
->smWaiting
->msg
== WM_RENDERFORMAT
154 && queue
->smWaiting
->hSrcQueue
158 /* FIXME: queue check no longer possible */
166 /**************************************************************************
167 * CLIPBOARD_ReleaseOwner
168 * Gives up ownership of the clipboard
170 void CLIPBOARD_ReleaseOwner()
176 /**************************************************************************
177 * CLIPBOARD_GlobalFreeProc
179 * This is a callback mechanism to allow HGLOBAL data to be released in
180 * the context of the process which allocated it. We post a WM_TIMER message
181 * to the owner window(in CLIPBOARD_DeleteRecord) and destroy the data(in idEvent)
182 * in this WndProc, which is invoked when the apps message loop calls DispatchMessage.
183 * This technique is discussed in Matt Pietrek's "Under the Hood".
184 * An article describing the same may be found in MSDN by searching for WM_TIMER.
185 * Note that this mechanism will probably stop working when WINE supports
186 * address space separation. When "queue events" are implemented in Wine we
187 * should switch to using that mechanism, since it is more robust and does not
188 * require a procedure address to be passed. See the SetWinEventHook API for
191 VOID CALLBACK
CLIPBOARD_GlobalFreeProc( HWND hwnd
, UINT uMsg
, UINT idEvent
, DWORD dwTime
)
193 /* idEvent is the HGLOBAL to be deleted */
194 GlobalFree( (HGLOBAL
)idEvent
);
197 /**************************************************************************
198 * CLIPBOARD_DeleteRecord
200 void CLIPBOARD_DeleteRecord(LPWINE_CLIPFORMAT lpFormat
, BOOL bChange
)
202 if( (lpFormat
->wFormatID
>= CF_GDIOBJFIRST
&&
203 lpFormat
->wFormatID
<= CF_GDIOBJLAST
) || lpFormat
->wFormatID
== CF_BITMAP
204 || lpFormat
->wFormatID
== CF_PALETTE
)
206 if (lpFormat
->hData32
)
207 DeleteObject(lpFormat
->hData32
);
208 if (lpFormat
->hData16
)
209 DeleteObject(lpFormat
->hData16
);
211 else if( lpFormat
->wFormatID
== CF_METAFILEPICT
)
213 if (lpFormat
->hData32
)
215 DeleteMetaFile( ((METAFILEPICT
*)GlobalLock( lpFormat
->hData32
))->hMF
);
216 PostMessageA(hWndClipOwner
, WM_TIMER
,
217 (WPARAM
)lpFormat
->hData32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
218 if (lpFormat
->hDataSrc32
)
220 /* Release lpFormat->hData32 in the context of the process which created it.
221 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
222 * GlobalFree(lpFormat->hDataSrc32);
224 PostMessageA(hWndClipOwner
, WM_TIMER
,
225 (WPARAM
)lpFormat
->hDataSrc32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
228 if (lpFormat
->hData16
)
229 /* HMETAFILE16 and HMETAFILE32 are apparently the same thing,
230 and a shallow copy is enough to share a METAFILEPICT
231 structure between 16bit and 32bit clipboards. The MetaFile
232 should of course only be deleted once. */
233 GlobalFree16(lpFormat
->hData16
);
235 if (lpFormat
->hData16
)
237 DeleteMetaFile16( ((METAFILEPICT16
*)GlobalLock16( lpFormat
->hData16
))->hMF
);
238 GlobalFree16(lpFormat
->hData16
);
243 if (lpFormat
->hData32
)
245 /* Release lpFormat->hData32 in the context of the process which created it.
246 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
247 * GlobalFree( lpFormat->hData32 );
249 PostMessageA(hWndClipOwner
, WM_TIMER
,
250 (WPARAM
)lpFormat
->hData32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
252 if (lpFormat
->hDataSrc32
)
254 /* Release lpFormat->hData32 in the context of the process which created it.
255 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
256 * GlobalFree(lpFormat->hDataSrc32);
258 PostMessageA(hWndClipOwner
, WM_TIMER
,
259 (WPARAM
)lpFormat
->hDataSrc32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
261 if (lpFormat
->hData16
)
262 GlobalFree16(lpFormat
->hData16
);
265 lpFormat
->wDataPresent
= 0;
266 lpFormat
->hData16
= 0;
267 lpFormat
->hData32
= 0;
268 lpFormat
->hDataSrc32
= 0;
269 lpFormat
->drvData
= 0;
271 if( bChange
) bCBHasChanged
= TRUE
;
274 /**************************************************************************
275 * CLIPBOARD_EmptyCache
277 void CLIPBOARD_EmptyCache( BOOL bChange
)
279 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
283 if ( lpFormat
->wDataPresent
|| lpFormat
->hData16
|| lpFormat
->hData32
)
284 CLIPBOARD_DeleteRecord( lpFormat
, bChange
);
286 lpFormat
= lpFormat
->NextFormat
;
290 /**************************************************************************
291 * CLIPBOARD_IsPresent
293 BOOL
CLIPBOARD_IsPresent(WORD wFormat
)
297 if( wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
|| wFormat
== CF_UNICODETEXT
)
298 return ClipFormats
[CF_TEXT
-1].wDataPresent
||
299 ClipFormats
[CF_OEMTEXT
-1].wDataPresent
||
300 ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
;
303 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
304 if( lpFormat
) return (lpFormat
->wDataPresent
);
309 /**************************************************************************
310 * CLIPBOARD_IsCacheRendered
311 * Checks if any data needs to be rendered to the clipboard cache
313 * TRUE - All clipboard data is available in the cache
314 * FALSE - Some data is marked for delayed render and needs rendering
316 BOOL
CLIPBOARD_IsCacheRendered()
318 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
320 /* check if all formats were rendered */
323 if( lpFormat
->wDataPresent
&& !lpFormat
->hData16
&& !lpFormat
->hData32
)
326 lpFormat
= lpFormat
->NextFormat
;
333 /**************************************************************************
334 * CLIPBOARD_IsMemoryObject
335 * Tests if the clipboard format specifies a memory object
337 BOOL
CLIPBOARD_IsMemoryObject( WORD wFormat
)
342 case CF_METAFILEPICT
:
354 /***********************************************************************
355 * CLIPBOARD_GlobalDupMem( HGLOBAL )
356 * Helper method to duplicate an HGLOBAL chunk of memory into shared memory
358 HGLOBAL
CLIPBOARD_GlobalDupMem( HGLOBAL hGlobalSrc
)
361 PVOID pGlobalSrc
, pGlobalDest
;
367 cBytes
= GlobalSize(hGlobalSrc
);
371 /* Turn on the DDESHARE and _MOVEABLE flags explicitly */
372 hGlobalDest
= GlobalAlloc( GlobalFlags(hGlobalSrc
) | GMEM_DDESHARE
| GMEM_MOVEABLE
,
377 pGlobalSrc
= GlobalLock(hGlobalSrc
);
378 pGlobalDest
= GlobalLock(hGlobalDest
);
379 if ( !pGlobalSrc
|| !pGlobalDest
)
382 memcpy(pGlobalDest
, pGlobalSrc
, cBytes
);
384 GlobalUnlock(hGlobalSrc
);
385 GlobalUnlock(hGlobalDest
);
390 /**************************************************************************
391 * CLIPBOARD_GetFormatName
392 * Gets the format name associated with an ID
394 char * CLIPBOARD_GetFormatName(UINT wFormat
)
396 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
397 return (lpFormat
) ? lpFormat
->Name
: NULL
;
401 /**************************************************************************
402 * CLIPBOARD_RenderFormat
404 static BOOL
CLIPBOARD_RenderFormat(LPWINE_CLIPFORMAT lpFormat
)
407 * If WINE is not the selection owner, and the format is available
408 * we must ask the driver to render the data to the clipboard cache.
410 TRACE("enter format=%d\n", lpFormat
->wFormatID
);
411 if ( !USER_Driver
.pIsSelectionOwner()
412 && USER_Driver
.pIsClipboardFormatAvailable( lpFormat
->wFormatID
) )
414 if ( !USER_Driver
.pGetClipboardData( lpFormat
->wFormatID
) )
418 * If Wine owns the clipboard, and the data is marked for delayed render,
421 else if( lpFormat
->wDataPresent
&& !lpFormat
->hData16
&& !lpFormat
->hData32
)
423 if( IsWindow(hWndClipOwner
) )
425 /* Send a WM_RENDERFORMAT message to notify the owner to render the
426 * data requested into the clipboard.
428 TRACE("Sending WM_RENDERFORMAT message\n");
429 SendMessageW( hWndClipOwner
, WM_RENDERFORMAT
, (WPARAM
)lpFormat
->wFormatID
, 0 );
433 WARN("\thWndClipOwner (%04x) is lost!\n",
435 CLIPBOARD_ReleaseOwner();
436 lpFormat
->wDataPresent
= 0;
441 return (lpFormat
->hData16
|| lpFormat
->hData32
) ? TRUE
: FALSE
;
444 /**************************************************************************
445 * CLIPBOARD_ConvertText
446 * Returns number of required/converted characters - not bytes!
448 static INT
CLIPBOARD_ConvertText(WORD src_fmt
, void const *src
, INT src_size
,
449 WORD dst_fmt
, void *dst
, INT dst_size
)
453 if(src_fmt
== CF_UNICODETEXT
)
466 return WideCharToMultiByte(cp
, 0, src
, src_size
, dst
, dst_size
, NULL
, NULL
);
469 if(dst_fmt
== CF_UNICODETEXT
)
482 return MultiByteToWideChar(cp
, 0, src
, src_size
, dst
, dst_size
);
485 if(!dst_size
) return src_size
;
487 if(dst_size
> src_size
) dst_size
= src_size
;
489 if(src_fmt
== CF_TEXT
)
490 CharToOemBuffA(src
, dst
, dst_size
);
492 OemToCharBuffA(src
, dst
, dst_size
);
497 /**************************************************************************
498 * CLIPBOARD_RenderText
500 * Renders text to the clipboard buffer converting between UNIX and DOS formats.
502 * RETURNS: pointer to the WINE_CLIPFORMAT if successful, NULL otherwise
504 * FIXME: Should be a pair of driver functions that convert between OEM text and Windows.
507 static LPWINE_CLIPFORMAT
CLIPBOARD_RenderText( UINT wFormat
)
509 LPWINE_CLIPFORMAT lpSource
= ClipFormats
;
510 LPWINE_CLIPFORMAT lpTarget
= NULL
;
511 BOOL foundData
= FALSE
;
513 /* Asked for CF_TEXT */
514 if( wFormat
== CF_TEXT
)
516 if(ClipFormats
[CF_TEXT
-1].wDataPresent
)
518 lpSource
= &ClipFormats
[CF_TEXT
-1];
519 lpTarget
= &ClipFormats
[CF_TEXT
-1];
521 TRACE("\t TEXT -> TEXT\n");
523 else if(ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
)
525 /* Convert UNICODETEXT -> TEXT */
526 lpSource
= &ClipFormats
[CF_UNICODETEXT
-1];
527 lpTarget
= &ClipFormats
[CF_TEXT
-1];
529 TRACE("\tUNICODETEXT -> TEXT\n");
531 else if(ClipFormats
[CF_OEMTEXT
-1].wDataPresent
)
533 /* Convert OEMTEXT -> TEXT */
534 lpSource
= &ClipFormats
[CF_OEMTEXT
-1];
535 lpTarget
= &ClipFormats
[CF_TEXT
-1];
537 TRACE("\tOEMTEXT -> TEXT\n");
540 /* Asked for CF_OEMTEXT */
541 else if( wFormat
== CF_OEMTEXT
)
543 if(ClipFormats
[CF_OEMTEXT
-1].wDataPresent
)
545 lpSource
= &ClipFormats
[CF_OEMTEXT
-1];
546 lpTarget
= &ClipFormats
[CF_OEMTEXT
-1];
548 TRACE("\tOEMTEXT -> OEMTEXT\n");
550 else if(ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
)
552 /* Convert UNICODETEXT -> OEMTEXT */
553 lpSource
= &ClipFormats
[CF_UNICODETEXT
-1];
554 lpTarget
= &ClipFormats
[CF_OEMTEXT
-1];
556 TRACE("\tUNICODETEXT -> OEMTEXT\n");
558 else if(ClipFormats
[CF_TEXT
-1].wDataPresent
)
560 /* Convert TEXT -> OEMTEXT */
561 lpSource
= &ClipFormats
[CF_TEXT
-1];
562 lpTarget
= &ClipFormats
[CF_OEMTEXT
-1];
564 TRACE("\tTEXT -> OEMTEXT\n");
567 /* Asked for CF_UNICODETEXT */
568 else if( wFormat
== CF_UNICODETEXT
)
570 if(ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
)
572 lpSource
= &ClipFormats
[CF_UNICODETEXT
-1];
573 lpTarget
= &ClipFormats
[CF_UNICODETEXT
-1];
575 TRACE("\tUNICODETEXT -> UNICODETEXT\n");
577 else if(ClipFormats
[CF_TEXT
-1].wDataPresent
)
579 /* Convert TEXT -> UNICODETEXT */
580 lpSource
= &ClipFormats
[CF_TEXT
-1];
581 lpTarget
= &ClipFormats
[CF_UNICODETEXT
-1];
583 TRACE("\tTEXT -> UNICODETEXT\n");
585 else if(ClipFormats
[CF_OEMTEXT
-1].wDataPresent
)
587 /* Convert OEMTEXT -> UNICODETEXT */
588 lpSource
= &ClipFormats
[CF_OEMTEXT
-1];
589 lpTarget
= &ClipFormats
[CF_UNICODETEXT
-1];
591 TRACE("\tOEMTEXT -> UNICODETEXT\n");
596 if ((wFormat
== CF_TEXT
) || (wFormat
== CF_OEMTEXT
))
598 lpSource
= &ClipFormats
[CF_UNICODETEXT
-1];
599 lpTarget
= __lookup_format( ClipFormats
, wFormat
);
603 lpSource
= __lookup_format( ClipFormats
, wFormat
);
608 /* First render the source text format */
609 if ( !lpSource
|| !CLIPBOARD_RenderFormat(lpSource
) ) return NULL
;
611 /* Convert to the desired target text format, if necessary */
612 if( lpTarget
!= lpSource
&& !lpTarget
->hData16
&& !lpTarget
->hData32
)
614 INT src_chars
, dst_chars
, alloc_size
;
618 if (lpSource
->hData32
)
620 lpstrS
= (LPSTR
)GlobalLock(lpSource
->hData32
);
624 lpstrS
= (LPSTR
)GlobalLock16(lpSource
->hData16
);
627 if( !lpstrS
) return NULL
;
629 /* Text always NULL terminated */
630 if(lpSource
->wFormatID
== CF_UNICODETEXT
)
631 src_chars
= strlenW((LPCWSTR
)lpstrS
)+1;
633 src_chars
= strlen(lpstrS
)+1;
635 /* Calculate number of characters in the destination buffer */
636 dst_chars
= CLIPBOARD_ConvertText(lpSource
->wFormatID
, lpstrS
, src_chars
,
637 lpTarget
->wFormatID
, NULL
, 0);
638 if(!dst_chars
) return NULL
;
640 TRACE("\tconverting from '%s' to '%s', %i chars\n",
641 lpSource
->Name
, lpTarget
->Name
, src_chars
);
643 /* Convert characters to bytes */
644 if(lpTarget
->wFormatID
== CF_UNICODETEXT
)
645 alloc_size
= dst_chars
* sizeof(WCHAR
);
647 alloc_size
= dst_chars
;
649 lpTarget
->hData32
= GlobalAlloc(GMEM_ZEROINIT
| GMEM_MOVEABLE
| GMEM_DDESHARE
, alloc_size
);
650 lpstrT
= (LPSTR
)GlobalLock(lpTarget
->hData32
);
654 CLIPBOARD_ConvertText(lpSource
->wFormatID
, lpstrS
, src_chars
,
655 lpTarget
->wFormatID
, lpstrT
, dst_chars
);
656 GlobalUnlock(lpTarget
->hData32
);
659 lpTarget
->hData32
= 0;
662 if (lpSource
->hData32
)
663 GlobalUnlock(lpSource
->hData32
);
665 GlobalUnlock16(lpSource
->hData16
);
668 return (lpTarget
->hData16
|| lpTarget
->hData32
) ? lpTarget
: NULL
;
671 /**************************************************************************
672 * CLIPBOARD_EnumClipboardFormats (internal)
674 static UINT
CLIPBOARD_EnumClipboardFormats( UINT wFormat
)
676 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
679 if (wFormat
== 0) /* start from the beginning */
680 lpFormat
= ClipFormats
;
683 /* walk up to the specified format record */
685 if( !(lpFormat
= __lookup_format( lpFormat
, wFormat
)) )
687 lpFormat
= lpFormat
->NextFormat
; /* right */
692 if (lpFormat
== NULL
) return 0;
694 if(CLIPBOARD_IsPresent(lpFormat
->wFormatID
))
697 /* Query the driver if not yet in the cache */
698 if (!USER_Driver
.pIsSelectionOwner())
700 if(lpFormat
->wFormatID
== CF_UNICODETEXT
||
701 lpFormat
->wFormatID
== CF_TEXT
||
702 lpFormat
->wFormatID
== CF_OEMTEXT
)
704 if(USER_Driver
.pIsClipboardFormatAvailable(CF_UNICODETEXT
) ||
705 USER_Driver
.pIsClipboardFormatAvailable(CF_TEXT
) ||
706 USER_Driver
.pIsClipboardFormatAvailable(CF_OEMTEXT
))
707 bFormatPresent
= TRUE
;
709 bFormatPresent
= FALSE
;
712 bFormatPresent
= USER_Driver
.pIsClipboardFormatAvailable(lpFormat
->wFormatID
);
718 lpFormat
= lpFormat
->NextFormat
;
721 TRACE("Next available format %d\n", lpFormat
->wFormatID
);
723 return lpFormat
->wFormatID
;
727 /**************************************************************************
728 * WIN32 Clipboard implementation
729 **************************************************************************/
731 /**************************************************************************
732 * OpenClipboard (USER32.@)
734 * Note: Netscape uses NULL hWnd to open the clipboard.
736 BOOL WINAPI
OpenClipboard( HWND hWnd
)
740 TRACE("(%04x)...\n", hWnd
);
744 hClipLock
= GetCurrentTask();
746 /* Save current user of the clipboard */
747 hWndClipWindow
= WIN_GetFullHandle( hWnd
);
748 bCBHasChanged
= FALSE
;
753 TRACE(" returning %i\n", bRet
);
758 /**************************************************************************
759 * CloseClipboard (USER.138)
761 BOOL16 WINAPI
CloseClipboard16(void)
763 return CloseClipboard();
767 /**************************************************************************
768 * CloseClipboard (USER32.@)
770 BOOL WINAPI
CloseClipboard(void)
774 if (hClipLock
== GetCurrentTask())
778 if (bCBHasChanged
&& hWndViewer
) SendMessageW( hWndViewer
, WM_DRAWCLIPBOARD
, 0, 0 );
785 /**************************************************************************
786 * EmptyClipboard (USER.139)
788 BOOL16 WINAPI
EmptyClipboard16(void)
790 return EmptyClipboard();
794 /**************************************************************************
795 * EmptyClipboard (USER32.@)
796 * Empties and acquires ownership of the clipboard
798 BOOL WINAPI
EmptyClipboard(void)
802 if (hClipLock
!= GetCurrentTask())
804 WARN("Clipboard not opened by calling task!\n");
808 /* destroy private objects */
810 if (hWndClipOwner
) SendMessageW( hWndClipOwner
, WM_DESTROYCLIPBOARD
, 0, 0 );
812 /* empty the cache */
813 CLIPBOARD_EmptyCache(TRUE
);
815 /* Assign ownership of the clipboard to the current client */
816 hWndClipOwner
= hWndClipWindow
;
818 /* Save the current task */
819 hTaskClipOwner
= GetCurrentTask();
821 /* Tell the driver to acquire the selection */
822 USER_Driver
.pAcquireClipboard();
828 /**************************************************************************
829 * GetClipboardOwner (USER32.@)
830 * FIXME: Can't return the owner if the clipbard is owned by an external app
832 HWND WINAPI
GetClipboardOwner(void)
835 return hWndClipOwner
;
839 /**************************************************************************
840 * SetClipboardData (USER.141)
842 HANDLE16 WINAPI
SetClipboardData16( UINT16 wFormat
, HANDLE16 hData
)
844 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
846 TRACE("(%04X, %04x) !\n", wFormat
, hData
);
848 /* NOTE: If the hData is zero and current owner doesn't match
849 * the window that opened the clipboard then this application
850 * is screwed because WM_RENDERFORMAT will go to the owner.
851 * (to become the owner it must call EmptyClipboard() before
855 if( CLIPBOARD_IsLocked() || !lpFormat
||
856 (!hData
&& (!hWndClipOwner
|| (hWndClipOwner
!= hWndClipWindow
))) )
858 WARN("Invalid hData or clipboard not opened by calling task!\n");
862 /* Pass on the request to the driver */
863 USER_Driver
.pSetClipboardData(wFormat
);
865 if ( lpFormat
->wDataPresent
|| lpFormat
->hData16
|| lpFormat
->hData32
)
867 CLIPBOARD_DeleteRecord(lpFormat
, TRUE
);
869 /* delete existing CF_UNICODETEXT/CF_TEXT/CF_OEMTEXT aliases */
870 if(wFormat
== CF_UNICODETEXT
)
872 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
873 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
875 else if(wFormat
== CF_TEXT
)
877 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_UNICODETEXT
-1], TRUE
);
878 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
880 else if(wFormat
== CF_OEMTEXT
)
882 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_UNICODETEXT
-1], TRUE
);
883 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
887 bCBHasChanged
= TRUE
;
888 lpFormat
->wDataPresent
= 1;
889 lpFormat
->hData16
= hData
; /* 0 is legal, see WM_RENDERFORMAT */
890 lpFormat
->hData32
= 0;
892 return lpFormat
->hData16
;
896 /**************************************************************************
897 * SetClipboardData (USER32.@)
899 HANDLE WINAPI
SetClipboardData( UINT wFormat
, HANDLE hData
)
901 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
903 TRACE("(%08X, %08x) !\n", wFormat
, hData
);
905 /* NOTE: If the hData is zero and current owner doesn't match
906 * the window that opened the clipboard then this application
907 * is screwed because WM_RENDERFORMAT will go to the owner.
908 * (to become the owner it must call EmptyClipboard() before
912 if( CLIPBOARD_IsLocked() || !lpFormat
||
913 (!hData
&& (!hWndClipOwner
|| (hWndClipOwner
!= hWndClipWindow
))) )
915 WARN("Invalid hData or clipboard not opened by calling task!\n");
919 /* Tell the driver to acquire the selection */
920 USER_Driver
.pAcquireClipboard();
922 if ( lpFormat
->wDataPresent
&&
923 (lpFormat
->hData16
|| lpFormat
->hData32
) )
925 CLIPBOARD_DeleteRecord(lpFormat
, TRUE
);
927 /* delete existing CF_UNICODETEXT/CF_TEXT/CF_OEMTEXT aliases */
928 if(wFormat
== CF_UNICODETEXT
)
930 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
931 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
933 else if(wFormat
== CF_TEXT
)
935 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_UNICODETEXT
-1], TRUE
);
936 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
938 else if(wFormat
== CF_OEMTEXT
)
940 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_UNICODETEXT
-1], TRUE
);
941 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
945 bCBHasChanged
= TRUE
;
946 lpFormat
->wDataPresent
= 1;
947 lpFormat
->hDataSrc32
= hData
; /* Save the source handle */
950 * Make a shared duplicate if the memory is not shared
951 * TODO: What should be done for non-memory objects
953 if ( CLIPBOARD_IsMemoryObject(wFormat
) && hData
&& !(GlobalFlags(hData
) & GMEM_DDESHARE
) )
954 lpFormat
->hData32
= CLIPBOARD_GlobalDupMem( hData
);
956 lpFormat
->hData32
= hData
; /* 0 is legal, see WM_RENDERFORMAT */
958 lpFormat
->hData16
= 0;
960 return lpFormat
->hData32
; /* Should we return lpFormat->hDataSrc32 */
964 /**************************************************************************
965 * GetClipboardData (USER.142)
967 HANDLE16 WINAPI
GetClipboardData16( UINT16 wFormat
)
969 LPWINE_CLIPFORMAT lpRender
= ClipFormats
;
971 TRACE("(%04X)\n", wFormat
);
973 if (CLIPBOARD_IsLocked())
975 WARN("Clipboard not opened by calling task!\n");
979 if( wFormat
== CF_UNICODETEXT
|| wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
)
981 lpRender
= CLIPBOARD_RenderText(wFormat
);
982 if ( !lpRender
) return 0;
986 lpRender
= __lookup_format( ClipFormats
, wFormat
);
987 if( !lpRender
|| !CLIPBOARD_RenderFormat(lpRender
) ) return 0;
990 /* Convert between 32 -> 16 bit data, if necessary */
991 if( lpRender
->hData32
&& !lpRender
->hData16
992 && CLIPBOARD_IsMemoryObject(wFormat
) )
995 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
996 size
= sizeof( METAFILEPICT16
);
998 size
= GlobalSize(lpRender
->hData32
);
1000 lpRender
->hData16
= GlobalAlloc16(GMEM_ZEROINIT
, size
);
1001 if( !lpRender
->hData16
)
1002 ERR("(%04X) -- not enough memory in 16b heap\n", wFormat
);
1005 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
1007 FIXME("\timplement function CopyMetaFilePict32to16\n");
1008 FIXME("\tin the appropriate file.\n");
1009 #ifdef SOMEONE_IMPLEMENTED_ME
1010 CopyMetaFilePict32to16( GlobalLock16(lpRender
->hData16
),
1011 GlobalLock(lpRender
->hData32
) );
1016 memcpy( GlobalLock16(lpRender
->hData16
),
1017 GlobalLock(lpRender
->hData32
),
1020 GlobalUnlock16(lpRender
->hData16
);
1021 GlobalUnlock(lpRender
->hData32
);
1025 TRACE("\treturning %04x (type %i)\n",
1026 lpRender
->hData16
, lpRender
->wFormatID
);
1027 return lpRender
->hData16
;
1031 /**************************************************************************
1032 * GetClipboardData (USER32.@)
1034 HANDLE WINAPI
GetClipboardData( UINT wFormat
)
1036 LPWINE_CLIPFORMAT lpRender
= ClipFormats
;
1038 TRACE("(%08X)\n", wFormat
);
1040 if (CLIPBOARD_IsLocked())
1042 WARN("Clipboard not opened by calling task!\n");
1046 if( wFormat
== CF_UNICODETEXT
|| wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
)
1048 lpRender
= CLIPBOARD_RenderText(wFormat
);
1049 if ( !lpRender
) return 0;
1053 lpRender
= __lookup_format( ClipFormats
, wFormat
);
1054 if( !lpRender
|| !CLIPBOARD_RenderFormat(lpRender
) ) return 0;
1057 /* Convert between 16 -> 32 bit data, if necessary */
1058 if( lpRender
->hData16
&& !lpRender
->hData32
1059 && CLIPBOARD_IsMemoryObject(wFormat
) )
1062 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
1063 size
= sizeof( METAFILEPICT
);
1065 size
= GlobalSize16(lpRender
->hData16
);
1066 lpRender
->hData32
= GlobalAlloc(GMEM_ZEROINIT
| GMEM_MOVEABLE
| GMEM_DDESHARE
,
1068 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
1070 FIXME("\timplement function CopyMetaFilePict16to32\n");
1071 FIXME("\tin the appropriate file.\n");
1072 #ifdef SOMEONE_IMPLEMENTED_ME
1073 CopyMetaFilePict16to32( GlobalLock16(lpRender
->hData32
),
1074 GlobalLock(lpRender
->hData16
) );
1079 memcpy( GlobalLock(lpRender
->hData32
),
1080 GlobalLock16(lpRender
->hData16
),
1083 GlobalUnlock(lpRender
->hData32
);
1084 GlobalUnlock16(lpRender
->hData16
);
1087 TRACE("\treturning %04x (type %i)\n",
1088 lpRender
->hData32
, lpRender
->wFormatID
);
1089 return lpRender
->hData32
;
1093 /**************************************************************************
1094 * CountClipboardFormats (USER.143)
1096 INT16 WINAPI
CountClipboardFormats16(void)
1098 return CountClipboardFormats();
1102 /**************************************************************************
1103 * CountClipboardFormats (USER32.@)
1105 INT WINAPI
CountClipboardFormats(void)
1107 INT FormatCount
= 0;
1108 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
1114 if (lpFormat
== NULL
) break;
1116 if( lpFormat
->wFormatID
!= CF_TEXT
) /* Don't count CF_TEXT */
1119 * The format is available if either:
1120 * 1. The data is already in the cache.
1121 * 2. The selection is not owned by us(WINE) and the data is
1122 * available to the clipboard driver.
1124 if ( lpFormat
->wDataPresent
||
1125 ( !USER_Driver
.pIsSelectionOwner()
1126 && USER_Driver
.pIsClipboardFormatAvailable( lpFormat
->wFormatID
) ) )
1128 TRACE("\tdata found for format 0x%04x(%s)\n",
1129 lpFormat
->wFormatID
, CLIPBOARD_GetFormatName(lpFormat
->wFormatID
));
1134 lpFormat
= lpFormat
->NextFormat
;
1137 /* these are equivalent, adjust the total */
1138 FormatCount
+= (ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
||
1139 ClipFormats
[CF_TEXT
-1].wDataPresent
||
1140 ClipFormats
[CF_OEMTEXT
-1].wDataPresent
) ? 1 : 0;
1142 TRACE("\ttotal %d\n", FormatCount
);
1146 /**************************************************************************
1147 * EnumClipboardFormats (USER.144)
1149 UINT16 WINAPI
EnumClipboardFormats16( UINT16 wFormat
)
1151 return EnumClipboardFormats( wFormat
);
1155 /**************************************************************************
1156 * EnumClipboardFormats (USER32.@)
1158 UINT WINAPI
EnumClipboardFormats( UINT wFormat
)
1160 TRACE("(%04X)\n", wFormat
);
1162 if (CLIPBOARD_IsLocked())
1164 WARN("Clipboard not opened by calling task!\n");
1168 return CLIPBOARD_EnumClipboardFormats(wFormat
);
1172 /**************************************************************************
1173 * RegisterClipboardFormatA (USER32.@)
1175 UINT WINAPI
RegisterClipboardFormatA( LPCSTR FormatName
)
1177 LPWINE_CLIPFORMAT lpNewFormat
;
1178 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
1180 if (FormatName
== NULL
) return 0;
1182 TRACE("('%s') !\n", FormatName
);
1184 /* walk format chain to see if it's already registered */
1188 if ( !strcmp(lpFormat
->Name
,FormatName
) )
1190 lpFormat
->wRefCount
++;
1191 return lpFormat
->wFormatID
;
1194 if ( lpFormat
->NextFormat
== NULL
) break;
1196 lpFormat
= lpFormat
->NextFormat
;
1199 /* allocate storage for new format entry */
1201 lpNewFormat
= (LPWINE_CLIPFORMAT
)HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_CLIPFORMAT
));
1202 if(lpNewFormat
== NULL
) {
1203 WARN("No more memory for a new format!\n");
1206 lpFormat
->NextFormat
= lpNewFormat
;
1207 lpNewFormat
->wFormatID
= LastRegFormat
;
1208 lpNewFormat
->wRefCount
= 1;
1210 if (!(lpNewFormat
->Name
= HeapAlloc(GetProcessHeap(), 0, strlen(FormatName
)+1 )))
1212 WARN("No more memory for the new format name!\n");
1213 HeapFree(GetProcessHeap(), 0, lpNewFormat
);
1216 strcpy( lpNewFormat
->Name
, FormatName
);
1218 lpNewFormat
->wDataPresent
= 0;
1219 lpNewFormat
->hData16
= 0;
1220 lpNewFormat
->hDataSrc32
= 0;
1221 lpNewFormat
->hData32
= 0;
1222 lpNewFormat
->drvData
= 0;
1223 lpNewFormat
->PrevFormat
= lpFormat
;
1224 lpNewFormat
->NextFormat
= NULL
;
1226 /* Pass on the registration request to the driver */
1227 USER_Driver
.pRegisterClipboardFormat( FormatName
);
1229 return LastRegFormat
++;
1233 /**************************************************************************
1234 * RegisterClipboardFormat (USER.145)
1236 UINT16 WINAPI
RegisterClipboardFormat16( LPCSTR FormatName
)
1238 return RegisterClipboardFormatA( FormatName
);
1242 /**************************************************************************
1243 * RegisterClipboardFormatW (USER32.@)
1245 UINT WINAPI
RegisterClipboardFormatW( LPCWSTR formatName
)
1247 LPSTR aFormat
= HEAP_strdupWtoA( GetProcessHeap(), 0, formatName
);
1248 UINT ret
= RegisterClipboardFormatA( aFormat
);
1249 HeapFree( GetProcessHeap(), 0, aFormat
);
1254 /**************************************************************************
1255 * GetClipboardFormatName (USER.146)
1257 INT16 WINAPI
GetClipboardFormatName16( UINT16 wFormat
, LPSTR retStr
, INT16 maxlen
)
1259 return GetClipboardFormatNameA( wFormat
, retStr
, maxlen
);
1263 /**************************************************************************
1264 * GetClipboardFormatNameA (USER32.@)
1266 INT WINAPI
GetClipboardFormatNameA( UINT wFormat
, LPSTR retStr
, INT maxlen
)
1268 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
1270 TRACE("(%04X, %p, %d) !\n", wFormat
, retStr
, maxlen
);
1272 if (lpFormat
== NULL
|| lpFormat
->Name
== NULL
||
1273 lpFormat
->wFormatID
< CF_REGFORMATBASE
) return 0;
1275 TRACE("Name='%s' !\n", lpFormat
->Name
);
1277 lstrcpynA( retStr
, lpFormat
->Name
, maxlen
);
1278 return strlen(retStr
);
1282 /**************************************************************************
1283 * GetClipboardFormatNameW (USER32.@)
1285 INT WINAPI
GetClipboardFormatNameW( UINT wFormat
, LPWSTR retStr
, INT maxlen
)
1288 LPSTR p
= HeapAlloc( GetProcessHeap(), 0, maxlen
);
1289 if(p
== NULL
) return 0; /* FIXME: is this the correct failure value? */
1291 ret
= GetClipboardFormatNameA( wFormat
, p
, maxlen
);
1293 if (maxlen
> 0 && !MultiByteToWideChar( CP_ACP
, 0, p
, -1, retStr
, maxlen
))
1294 retStr
[maxlen
-1] = 0;
1295 HeapFree( GetProcessHeap(), 0, p
);
1300 /**************************************************************************
1301 * SetClipboardViewer (USER32.@)
1303 HWND WINAPI
SetClipboardViewer( HWND hWnd
)
1305 HWND hwndPrev
= hWndViewer
;
1307 TRACE("(%04x): returning %04x\n", hWnd
, hwndPrev
);
1309 hWndViewer
= WIN_GetFullHandle( hWnd
);
1314 /**************************************************************************
1315 * GetClipboardViewer (USER32.@)
1317 HWND WINAPI
GetClipboardViewer(void)
1324 /**************************************************************************
1325 * ChangeClipboardChain (USER32.@)
1327 BOOL WINAPI
ChangeClipboardChain(HWND hWnd
, HWND hWndNext
)
1331 FIXME("(0x%04x, 0x%04x): stub?\n", hWnd
, hWndNext
);
1334 bRet
= !SendMessageW( hWndViewer
, WM_CHANGECBCHAIN
, (WPARAM
)hWnd
, (LPARAM
)hWndNext
);
1336 WARN("hWndViewer is lost\n");
1338 if( WIN_GetFullHandle(hWnd
) == hWndViewer
) hWndViewer
= WIN_GetFullHandle( hWndNext
);
1344 /**************************************************************************
1345 * IsClipboardFormatAvailable (USER.193)
1347 BOOL16 WINAPI
IsClipboardFormatAvailable16( UINT16 wFormat
)
1349 return IsClipboardFormatAvailable( wFormat
);
1353 /**************************************************************************
1354 * IsClipboardFormatAvailable (USER32.@)
1356 BOOL WINAPI
IsClipboardFormatAvailable( UINT wFormat
)
1360 if (wFormat
== 0) /* Reject this case quickly */
1364 UINT iret
= CLIPBOARD_EnumClipboardFormats(wFormat
- 1);
1365 if ((wFormat
== CF_TEXT
) || (wFormat
== CF_OEMTEXT
) || (wFormat
== CF_UNICODETEXT
))
1366 bRet
= ((iret
== CF_TEXT
) || (iret
== CF_OEMTEXT
) || (iret
== CF_UNICODETEXT
));
1368 bRet
= iret
== wFormat
;
1370 TRACE("(%04X)- ret(%d)\n", wFormat
, bRet
);
1375 /**************************************************************************
1376 * GetOpenClipboardWindow (USER32.@)
1377 * FIXME: This wont work if an external app owns the selection
1379 HWND WINAPI
GetOpenClipboardWindow(void)
1382 return hWndClipWindow
;
1386 /**************************************************************************
1387 * GetPriorityClipboardFormat (USER32.@)
1389 INT WINAPI
GetPriorityClipboardFormat( UINT
*list
, INT nCount
)
1394 if(CountClipboardFormats() == 0) return 0;
1396 for (i
= 0; i
< nCount
; i
++)
1397 if (IsClipboardFormatAvailable( list
[i
] )) return list
[i
];
1402 /**************************************************************************
1403 * GetClipboardSequenceNumber (USER32.@)
1404 * Supported on Win2k/Win98
1405 * MSDN: Windows clipboard code keeps a serial number for the clipboard
1406 * for each window station. The number is incremented whenever the
1407 * contents change or are emptied.
1408 * If you do not have WINSTA_ACCESSCLIPBOARD then the function returns 0
1410 DWORD WINAPI
GetClipboardSequenceNumber(VOID
)
1412 FIXME("Returning 0, see windows/clipboard.c\n");
1413 /* FIXME: Use serial numbers */