2 * WIN32 clipboard implementation
4 * Copyright 1994 Martin Ayotte
9 * This file contains the implementation for the WIN32 Clipboard API
10 * and Wine's internal clipboard cache.
11 * The actual contents of the clipboard are held in the clipboard cache.
12 * The internal implementation talks to a "clipboard driver" to fill or
13 * expose the cache to the native device. (Currently only the X11 and
14 * TTY clipboard driver are available)
21 #include <sys/types.h>
29 #include "wine/winuser16.h"
30 #include "wine/winbase16.h"
36 #include "clipboard.h"
37 #include "debugtools.h"
39 DEFAULT_DEBUG_CHANNEL(clipboard
);
41 #define CF_REGFORMATBASE 0xC000
43 /**************************************************************************
44 * Clipboard context global variables
47 static HANDLE hClipLock
= 0;
48 static BOOL bCBHasChanged
= FALSE
;
50 HWND hWndClipWindow
= 0; /* window that last opened clipboard */
51 HWND hWndClipOwner
= 0; /* current clipboard owner */
52 HANDLE16 hTaskClipOwner
= 0; /* clipboard owner's task */
53 static HWND hWndViewer
= 0; /* start of viewers chain */
55 static WORD LastRegFormat
= CF_REGFORMATBASE
;
57 /* Clipboard cache initial data.
58 * WARNING: This data ordering is dependendent on the WINE_CLIPFORMAT structure
59 * declared in clipboard.h
61 WINE_CLIPFORMAT ClipFormats
[] = {
62 { CF_TEXT
, 1, 0, "Text", 0, 0, 0, 0, NULL
, &ClipFormats
[1]},
63 { CF_BITMAP
, 1, 0, "Bitmap", 0, 0, 0, 0, &ClipFormats
[0], &ClipFormats
[2]},
64 { CF_METAFILEPICT
, 1, 0, "MetaFile Picture", 0, 0, 0, 0, &ClipFormats
[1], &ClipFormats
[3]},
65 { CF_SYLK
, 1, 0, "Sylk", 0, 0, 0, 0, &ClipFormats
[2], &ClipFormats
[4]},
66 { CF_DIF
, 1, 0, "DIF", 0, 0, 0, 0, &ClipFormats
[3], &ClipFormats
[5]},
67 { CF_TIFF
, 1, 0, "TIFF", 0, 0, 0, 0, &ClipFormats
[4], &ClipFormats
[6]},
68 { CF_OEMTEXT
, 1, 0, "OEM Text", 0, 0, 0, 0, &ClipFormats
[5], &ClipFormats
[7]},
69 { CF_DIB
, 1, 0, "DIB", 0, 0, 0, 0, &ClipFormats
[6], &ClipFormats
[8]},
70 { CF_PALETTE
, 1, 0, "Palette", 0, 0, 0, 0, &ClipFormats
[7], &ClipFormats
[9]},
71 { CF_PENDATA
, 1, 0, "PenData", 0, 0, 0, 0, &ClipFormats
[8], &ClipFormats
[10]},
72 { CF_RIFF
, 1, 0, "RIFF", 0, 0, 0, 0, &ClipFormats
[9], &ClipFormats
[11]},
73 { CF_WAVE
, 1, 0, "Wave", 0, 0, 0, 0, &ClipFormats
[10], &ClipFormats
[12]},
74 { CF_UNICODETEXT
, 1, 0, "Unicode Text", 0, 0, 0, 0, &ClipFormats
[11], &ClipFormats
[13]},
75 { CF_OWNERDISPLAY
, 1, 0, "Owner Display", 0, 0, 0, 0, &ClipFormats
[12], &ClipFormats
[14]},
76 { CF_DSPTEXT
, 1, 0, "DSPText", 0, 0, 0, 0, &ClipFormats
[13], &ClipFormats
[15]},
77 { CF_DSPMETAFILEPICT
, 1, 0, "DSPMetaFile Picture", 0, 0, 0, 0, &ClipFormats
[14], &ClipFormats
[16]},
78 { CF_DSPBITMAP
, 1, 0, "DSPBitmap", 0, 0, 0, 0, &ClipFormats
[15], &ClipFormats
[17]},
79 { CF_HDROP
, 1, 0, "HDROP", 0, 0, 0, 0, &ClipFormats
[16], NULL
}
83 /**************************************************************************
84 * Internal Clipboard implementation methods
85 **************************************************************************/
88 /**************************************************************************
89 * CLIPBOARD_LookupFormat
91 static LPWINE_CLIPFORMAT
__lookup_format( LPWINE_CLIPFORMAT lpFormat
, WORD wID
)
95 if (lpFormat
== NULL
||
96 lpFormat
->wFormatID
== wID
) break;
97 lpFormat
= lpFormat
->NextFormat
;
102 LPWINE_CLIPFORMAT
CLIPBOARD_LookupFormat( WORD wID
)
104 return __lookup_format( ClipFormats
, wID
);
107 /**************************************************************************
109 * Check if the clipboard cache is available to the caller
111 BOOL
CLIPBOARD_IsLocked()
113 BOOL bIsLocked
= TRUE
;
114 HANDLE16 hTaskCur
= GetCurrentTask();
117 * The clipboard is available:
118 * 1. if the caller's task has opened the clipboard,
120 * 2. if the caller is the clipboard owners task, AND is responding to a
121 * WM_RENDERFORMAT message.
123 if ( hClipLock
== hTaskCur
)
126 else if ( hTaskCur
== hTaskClipOwner
)
128 /* Check if we're currently executing inside a window procedure
129 * called in response to a WM_RENDERFORMAT message. A WM_RENDERFORMAT
130 * handler is not permitted to open the clipboard since it has been opened
131 * by another client. However the handler must have access to the
132 * 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
);
149 /**************************************************************************
150 * CLIPBOARD_ReleaseOwner
151 * Gives up ownership of the clipboard
153 void CLIPBOARD_ReleaseOwner()
159 /**************************************************************************
160 * CLIPBOARD_GlobalFreeProc
162 * This is a callback mechanism to allow HGLOBAL data to be released in
163 * the context of the process which allocated it. We post a WM_TIMER message
164 * to the owner window(in CLIPBOARD_DeleteRecord) and destroy the data(in idEvent)
165 * in this WndProc, which is invoked when the apps message loop calls DispatchMessage.
166 * This technique is discussed in Matt Pietrek's "Under the Hood".
167 * An article describing the same may be found in MSDN by searching for WM_TIMER.
168 * Note that this mechanism will probably stop working when WINE supports
169 * address space separation. When "queue events" are implemented in Wine we
170 * should switch to using that mechanism, since it is more robust and does not
171 * require a procedure address to be passed. See the SetWinEventHook API for
174 VOID CALLBACK
CLIPBOARD_GlobalFreeProc( HWND hwnd
, UINT uMsg
, UINT idEvent
, DWORD dwTime
)
176 /* idEvent is the HGLOBAL to be deleted */
177 GlobalFree( (HGLOBAL
)idEvent
);
180 /**************************************************************************
181 * CLIPBOARD_DeleteRecord
183 void CLIPBOARD_DeleteRecord(LPWINE_CLIPFORMAT lpFormat
, BOOL bChange
)
185 if( (lpFormat
->wFormatID
>= CF_GDIOBJFIRST
&&
186 lpFormat
->wFormatID
<= CF_GDIOBJLAST
) || lpFormat
->wFormatID
== CF_BITMAP
187 || lpFormat
->wFormatID
== CF_PALETTE
)
189 if (lpFormat
->hData32
)
190 DeleteObject(lpFormat
->hData32
);
191 if (lpFormat
->hData16
)
192 DeleteObject(lpFormat
->hData16
);
194 else if( lpFormat
->wFormatID
== CF_METAFILEPICT
)
196 if (lpFormat
->hData32
)
198 DeleteMetaFile( ((METAFILEPICT
*)GlobalLock( lpFormat
->hData32
))->hMF
);
199 PostMessageA(hWndClipOwner
, WM_TIMER
,
200 (WPARAM
)lpFormat
->hData32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
201 if (lpFormat
->hDataSrc32
)
203 /* Release lpFormat->hData32 in the context of the process which created it.
204 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
205 * GlobalFree(lpFormat->hDataSrc32);
207 PostMessageA(hWndClipOwner
, WM_TIMER
,
208 (WPARAM
)lpFormat
->hDataSrc32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
211 if (lpFormat
->hData16
)
212 /* HMETAFILE16 and HMETAFILE32 are apparently the same thing,
213 and a shallow copy is enough to share a METAFILEPICT
214 structure between 16bit and 32bit clipboards. The MetaFile
215 should of course only be deleted once. */
216 GlobalFree16(lpFormat
->hData16
);
218 if (lpFormat
->hData16
)
220 DeleteMetaFile16( ((METAFILEPICT16
*)GlobalLock16( lpFormat
->hData16
))->hMF
);
221 GlobalFree16(lpFormat
->hData16
);
226 if (lpFormat
->hData32
)
228 /* Release lpFormat->hData32 in the context of the process which created it.
229 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
230 * GlobalFree( lpFormat->hData32 );
232 PostMessageA(hWndClipOwner
, WM_TIMER
,
233 (WPARAM
)lpFormat
->hData32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
235 if (lpFormat
->hDataSrc32
)
237 /* Release lpFormat->hData32 in the context of the process which created it.
238 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
239 * GlobalFree(lpFormat->hDataSrc32);
241 PostMessageA(hWndClipOwner
, WM_TIMER
,
242 (WPARAM
)lpFormat
->hDataSrc32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
244 if (lpFormat
->hData16
)
245 GlobalFree16(lpFormat
->hData16
);
248 lpFormat
->wDataPresent
= 0;
249 lpFormat
->hData16
= 0;
250 lpFormat
->hData32
= 0;
251 lpFormat
->hDataSrc32
= 0;
252 lpFormat
->drvData
= 0;
254 if( bChange
) bCBHasChanged
= TRUE
;
257 /**************************************************************************
258 * CLIPBOARD_EmptyCache
260 void CLIPBOARD_EmptyCache( BOOL bChange
)
262 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
266 if ( lpFormat
->wDataPresent
|| lpFormat
->hData16
|| lpFormat
->hData32
)
267 CLIPBOARD_DeleteRecord( lpFormat
, bChange
);
269 lpFormat
= lpFormat
->NextFormat
;
273 /**************************************************************************
274 * CLIPBOARD_IsPresent
276 BOOL
CLIPBOARD_IsPresent(WORD wFormat
)
280 if( wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
|| wFormat
== CF_UNICODETEXT
)
281 return ClipFormats
[CF_TEXT
-1].wDataPresent
||
282 ClipFormats
[CF_OEMTEXT
-1].wDataPresent
||
283 ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
;
286 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
287 if( lpFormat
) return (lpFormat
->wDataPresent
);
292 /**************************************************************************
293 * CLIPBOARD_IsCacheRendered
294 * Checks if any data needs to be rendered to the clipboard cache
296 * TRUE - All clipboard data is available in the cache
297 * FALSE - Some data is marked for delayed render and needs rendering
299 BOOL
CLIPBOARD_IsCacheRendered()
301 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
303 /* check if all formats were rendered */
306 if( lpFormat
->wDataPresent
&& !lpFormat
->hData16
&& !lpFormat
->hData32
)
309 lpFormat
= lpFormat
->NextFormat
;
316 /**************************************************************************
317 * CLIPBOARD_IsMemoryObject
318 * Tests if the clipboard format specifies a memory object
320 BOOL
CLIPBOARD_IsMemoryObject( WORD wFormat
)
325 case CF_METAFILEPICT
:
337 /***********************************************************************
338 * CLIPBOARD_GlobalDupMem( HGLOBAL )
339 * Helper method to duplicate an HGLOBAL chunk of memory into shared memory
341 HGLOBAL
CLIPBOARD_GlobalDupMem( HGLOBAL hGlobalSrc
)
344 PVOID pGlobalSrc
, pGlobalDest
;
350 cBytes
= GlobalSize(hGlobalSrc
);
354 /* Turn on the DDESHARE and _MOVEABLE flags explicitly */
355 hGlobalDest
= GlobalAlloc( GlobalFlags(hGlobalSrc
) | GMEM_DDESHARE
| GMEM_MOVEABLE
,
360 pGlobalSrc
= GlobalLock(hGlobalSrc
);
361 pGlobalDest
= GlobalLock(hGlobalDest
);
362 if ( !pGlobalSrc
|| !pGlobalDest
)
365 memcpy(pGlobalDest
, pGlobalSrc
, cBytes
);
367 GlobalUnlock(hGlobalSrc
);
368 GlobalUnlock(hGlobalDest
);
373 /**************************************************************************
374 * CLIPBOARD_GetFormatName
375 * Gets the format name associated with an ID
377 char * CLIPBOARD_GetFormatName(UINT wFormat
)
379 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
380 return (lpFormat
) ? lpFormat
->Name
: NULL
;
384 /**************************************************************************
385 * CLIPBOARD_RenderFormat
387 static BOOL
CLIPBOARD_RenderFormat(LPWINE_CLIPFORMAT lpFormat
)
390 * If WINE is not the selection owner, and the format is available
391 * we must ask the the driver to render the data to the clipboard cache.
393 if ( !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 SendMessage16(hWndClipOwner
,WM_RENDERFORMAT
,
412 (WPARAM16
)lpFormat
->wFormatID
,0L);
416 WARN("\thWndClipOwner (%04x) is lost!\n",
418 CLIPBOARD_ReleaseOwner();
419 lpFormat
->wDataPresent
= 0;
424 return (lpFormat
->hData16
|| lpFormat
->hData32
) ? TRUE
: FALSE
;
427 /**************************************************************************
428 * CLIPBOARD_ConvertText
429 * Returns number of required/converted characters - not bytes!
431 static INT
CLIPBOARD_ConvertText(WORD src_fmt
, void const *src
, INT src_size
,
432 WORD dst_fmt
, void *dst
, INT dst_size
)
436 if(src_fmt
== CF_UNICODETEXT
)
449 return WideCharToMultiByte(cp
, 0, src
, src_size
, dst
, dst_size
, NULL
, NULL
);
452 if(dst_fmt
== CF_UNICODETEXT
)
465 return MultiByteToWideChar(cp
, 0, src
, src_size
, dst
, dst_size
);
468 if(!dst_size
) return src_size
;
470 if(dst_size
> src_size
) dst_size
= src_size
;
472 if(src_fmt
== CF_TEXT
)
473 CharToOemBuffA(src
, dst
, dst_size
);
475 OemToCharBuffA(src
, dst
, dst_size
);
480 /**************************************************************************
481 * CLIPBOARD_RenderText
483 * Renders text to the clipboard buffer converting between UNIX and DOS formats.
485 * RETURNS: pointer to the WINE_CLIPFORMAT if successful, NULL otherwise
487 * FIXME: Should be a pair of driver functions that convert between OEM text and Windows.
490 static LPWINE_CLIPFORMAT
CLIPBOARD_RenderText( UINT wFormat
)
492 LPWINE_CLIPFORMAT lpSource
= ClipFormats
;
493 LPWINE_CLIPFORMAT lpTarget
;
495 /* Asked for CF_TEXT but not available - always attempt to convert
496 from CF_UNICODETEXT or CF_OEMTEXT */
497 if( wFormat
== CF_TEXT
&& !ClipFormats
[CF_TEXT
-1].wDataPresent
)
499 if(ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
)
501 /* Convert UNICODETEXT -> TEXT */
502 lpSource
= &ClipFormats
[CF_UNICODETEXT
-1];
503 lpTarget
= &ClipFormats
[CF_TEXT
-1];
505 TRACE("\tUNICODETEXT -> TEXT\n");
507 else if(ClipFormats
[CF_OEMTEXT
-1].wDataPresent
)
509 /* Convert OEMTEXT -> TEXT */
510 lpSource
= &ClipFormats
[CF_OEMTEXT
-1];
511 lpTarget
= &ClipFormats
[CF_TEXT
-1];
513 TRACE("\tOEMTEXT -> TEXT\n");
516 lpSource
= NULL
; /* Conversion format is not available */
518 /* Asked for CF_OEMTEXT but not available - always attempt to convert
519 from CF_UNICODETEXT or CF_TEXT */
520 else if( wFormat
== CF_OEMTEXT
&& !ClipFormats
[CF_OEMTEXT
-1].wDataPresent
)
522 if(ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
)
524 /* Convert UNICODETEXT -> OEMTEXT */
525 lpSource
= &ClipFormats
[CF_UNICODETEXT
-1];
526 lpTarget
= &ClipFormats
[CF_OEMTEXT
-1];
528 TRACE("\tUNICODETEXT -> OEMTEXT\n");
530 else if(ClipFormats
[CF_TEXT
-1].wDataPresent
)
532 /* Convert TEXT -> OEMTEXT */
533 lpSource
= &ClipFormats
[CF_TEXT
-1];
534 lpTarget
= &ClipFormats
[CF_OEMTEXT
-1];
536 TRACE("\tTEXT -> OEMTEXT\n");
539 lpSource
= NULL
; /* Conversion format is not available */
541 /* Asked for CF_UNICODETEXT but not available - always attempt to convert
542 from CF_TEXT or CF_OEMTEXT */
543 else if( wFormat
== CF_UNICODETEXT
&& !ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
)
545 if(ClipFormats
[CF_TEXT
-1].wDataPresent
)
547 /* Convert TEXT -> UNICODETEXT */
548 lpSource
= &ClipFormats
[CF_TEXT
-1];
549 lpTarget
= &ClipFormats
[CF_UNICODETEXT
-1];
551 TRACE("\tTEXT -> UNICODETEXT\n");
553 else if(ClipFormats
[CF_OEMTEXT
-1].wDataPresent
)
555 /* Convert OEMTEXT -> UNICODETEXT */
556 lpSource
= &ClipFormats
[CF_OEMTEXT
-1];
557 lpTarget
= &ClipFormats
[CF_UNICODETEXT
-1];
559 TRACE("\tOEMTEXT -> UNICODETEXT\n");
562 lpSource
= NULL
; /* Conversion format is not available */
564 /* Text format requested is available - no conversion necessary */
567 lpSource
= __lookup_format( ClipFormats
, wFormat
);
571 /* First render the source text format */
572 if ( !lpSource
|| !CLIPBOARD_RenderFormat(lpSource
) ) return NULL
;
574 /* Convert to the desired target text format, if necessary */
575 if( lpTarget
!= lpSource
&& !lpTarget
->hData16
&& !lpTarget
->hData32
)
577 INT src_chars
, dst_chars
, alloc_size
;
581 if (lpSource
->hData32
)
583 lpstrS
= (LPSTR
)GlobalLock(lpSource
->hData32
);
587 lpstrS
= (LPSTR
)GlobalLock16(lpSource
->hData16
);
590 if( !lpstrS
) return NULL
;
592 /* Text always NULL terminated */
593 if(lpSource
->wFormatID
== CF_UNICODETEXT
)
594 src_chars
= strlenW((LPCWSTR
)lpstrS
);
596 src_chars
= strlen(lpstrS
);
598 /* Calculate number of characters in the destination buffer */
599 dst_chars
= CLIPBOARD_ConvertText(lpSource
->wFormatID
, lpstrS
, src_chars
,
600 lpTarget
->wFormatID
, NULL
, 0);
601 if(!dst_chars
) return NULL
;
603 TRACE("\tconverting from '%s' to '%s', %i chars\n",
604 lpSource
->Name
, lpTarget
->Name
, src_chars
);
606 /* Convert characters to bytes */
607 if(lpTarget
->wFormatID
== CF_UNICODETEXT
)
608 alloc_size
= dst_chars
* sizeof(WCHAR
);
610 alloc_size
= dst_chars
;
612 lpTarget
->hData32
= GlobalAlloc(GMEM_ZEROINIT
| GMEM_MOVEABLE
| GMEM_DDESHARE
, alloc_size
);
613 lpstrT
= (LPSTR
)GlobalLock(lpTarget
->hData32
);
617 CLIPBOARD_ConvertText(lpSource
->wFormatID
, lpstrS
, src_chars
,
618 lpTarget
->wFormatID
, lpstrT
, dst_chars
);
619 GlobalUnlock(lpTarget
->hData32
);
622 lpTarget
->hData32
= 0;
625 if (lpSource
->hData32
)
626 GlobalUnlock(lpSource
->hData32
);
628 GlobalUnlock16(lpSource
->hData16
);
631 return (lpTarget
->hData16
|| lpTarget
->hData32
) ? lpTarget
: NULL
;
634 /**************************************************************************
635 * WIN32 Clipboard implementation
636 **************************************************************************/
638 /**************************************************************************
639 * OpenClipboard16 (USER.137)
641 BOOL16 WINAPI
OpenClipboard16( HWND16 hWnd
)
643 return OpenClipboard( hWnd
);
647 /**************************************************************************
648 * OpenClipboard (USER32.407)
650 * Note: Netscape uses NULL hWnd to open the clipboard.
652 BOOL WINAPI
OpenClipboard( HWND hWnd
)
656 TRACE("(%04x)...\n", hWnd
);
660 hClipLock
= GetCurrentTask();
662 /* Save current user of the clipboard */
663 hWndClipWindow
= hWnd
;
664 bCBHasChanged
= FALSE
;
669 TRACE(" returning %i\n", bRet
);
674 /**************************************************************************
675 * CloseClipboard16 (USER.138)
677 BOOL16 WINAPI
CloseClipboard16(void)
679 return CloseClipboard();
683 /**************************************************************************
684 * CloseClipboard (USER32.54)
686 BOOL WINAPI
CloseClipboard(void)
690 if (hClipLock
== GetCurrentTask())
694 if (bCBHasChanged
&& hWndViewer
)
695 SendMessage16(hWndViewer
, WM_DRAWCLIPBOARD
, 0, 0L);
702 /**************************************************************************
703 * EmptyClipboard16 (USER.139)
705 BOOL16 WINAPI
EmptyClipboard16(void)
707 return EmptyClipboard();
711 /**************************************************************************
712 * EmptyClipboard (USER32.169)
713 * Empties and acquires ownership of the clipboard
715 BOOL WINAPI
EmptyClipboard(void)
719 if (hClipLock
!= GetCurrentTask())
721 WARN("Clipboard not opened by calling task!");
725 /* destroy private objects */
728 SendMessage16(hWndClipOwner
, WM_DESTROYCLIPBOARD
, 0, 0L);
730 /* empty the cache */
731 CLIPBOARD_EmptyCache(TRUE
);
733 /* Assign ownership of the clipboard to the current client */
734 hWndClipOwner
= hWndClipWindow
;
736 /* Save the current task */
737 hTaskClipOwner
= GetCurrentTask();
739 /* Tell the driver to acquire the selection */
740 USER_Driver
.pAcquireClipboard();
746 /**************************************************************************
747 * GetClipboardOwner16 (USER.140)
748 * FIXME: Can't return the owner if the clipbard is owned by an external app
750 HWND16 WINAPI
GetClipboardOwner16(void)
753 return hWndClipOwner
;
757 /**************************************************************************
758 * GetClipboardOwner (USER32.225)
759 * FIXME: Can't return the owner if the clipbard is owned by an external app
761 HWND WINAPI
GetClipboardOwner(void)
764 return hWndClipOwner
;
768 /**************************************************************************
769 * SetClipboardData16 (USER.141)
771 HANDLE16 WINAPI
SetClipboardData16( UINT16 wFormat
, HANDLE16 hData
)
773 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
775 TRACE("(%04X, %04x) !\n", wFormat
, hData
);
777 /* NOTE: If the hData is zero and current owner doesn't match
778 * the window that opened the clipboard then this application
779 * is screwed because WM_RENDERFORMAT will go to the owner.
780 * (to become the owner it must call EmptyClipboard() before
784 if( CLIPBOARD_IsLocked() || !lpFormat
||
785 (!hData
&& (!hWndClipOwner
|| (hWndClipOwner
!= hWndClipWindow
))) )
787 WARN("Invalid hData or clipboard not opened by calling task!\n");
791 /* Pass on the request to the driver */
792 USER_Driver
.pSetClipboardData(wFormat
);
794 if ( lpFormat
->wDataPresent
|| lpFormat
->hData16
|| lpFormat
->hData32
)
796 CLIPBOARD_DeleteRecord(lpFormat
, TRUE
);
798 /* delete existing CF_UNICODETEXT/CF_TEXT/CF_OEMTEXT aliases */
799 if(wFormat
== CF_UNICODETEXT
)
801 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
802 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
804 else if(wFormat
== CF_TEXT
)
806 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_UNICODETEXT
-1], TRUE
);
807 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
809 else if(wFormat
== CF_OEMTEXT
)
811 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_UNICODETEXT
-1], TRUE
);
812 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
816 bCBHasChanged
= TRUE
;
817 lpFormat
->wDataPresent
= 1;
818 lpFormat
->hData16
= hData
; /* 0 is legal, see WM_RENDERFORMAT */
819 lpFormat
->hData32
= 0;
821 return lpFormat
->hData16
;
825 /**************************************************************************
826 * SetClipboardData (USER32.470)
828 HANDLE WINAPI
SetClipboardData( UINT wFormat
, HANDLE hData
)
830 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
832 TRACE("(%08X, %08x) !\n", wFormat
, hData
);
834 /* NOTE: If the hData is zero and current owner doesn't match
835 * the window that opened the clipboard then this application
836 * is screwed because WM_RENDERFORMAT will go to the owner.
837 * (to become the owner it must call EmptyClipboard() before
841 if( CLIPBOARD_IsLocked() || !lpFormat
||
842 (!hData
&& (!hWndClipOwner
|| (hWndClipOwner
!= hWndClipWindow
))) )
844 WARN("Invalid hData or clipboard not opened by calling task!\n");
848 /* Tell the driver to acquire the selection */
849 USER_Driver
.pAcquireClipboard();
851 if ( lpFormat
->wDataPresent
&&
852 (lpFormat
->hData16
|| lpFormat
->hData32
) )
854 CLIPBOARD_DeleteRecord(lpFormat
, TRUE
);
856 /* delete existing CF_UNICODETEXT/CF_TEXT/CF_OEMTEXT aliases */
857 if(wFormat
== CF_UNICODETEXT
)
859 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
860 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
862 else if(wFormat
== CF_TEXT
)
864 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_UNICODETEXT
-1], TRUE
);
865 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
867 else if(wFormat
== CF_OEMTEXT
)
869 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_UNICODETEXT
-1], TRUE
);
870 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
874 bCBHasChanged
= TRUE
;
875 lpFormat
->wDataPresent
= 1;
876 lpFormat
->hDataSrc32
= hData
; /* Save the source handle */
879 * Make a shared duplicate if the memory is not shared
880 * TODO: What should be done for non-memory objects
882 if ( CLIPBOARD_IsMemoryObject(wFormat
) && hData
&& !(GlobalFlags(hData
) & GMEM_DDESHARE
) )
883 lpFormat
->hData32
= CLIPBOARD_GlobalDupMem( hData
);
885 lpFormat
->hData32
= hData
; /* 0 is legal, see WM_RENDERFORMAT */
887 lpFormat
->hData16
= 0;
889 return lpFormat
->hData32
; /* Should we return lpFormat->hDataSrc32 */
893 /**************************************************************************
894 * GetClipboardData16 (USER.142)
896 HANDLE16 WINAPI
GetClipboardData16( UINT16 wFormat
)
898 LPWINE_CLIPFORMAT lpRender
= ClipFormats
;
900 TRACE("(%04X)\n", wFormat
);
902 if (CLIPBOARD_IsLocked())
904 WARN("Clipboard not opened by calling task!\n");
908 if( wFormat
== CF_UNICODETEXT
|| wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
)
910 lpRender
= CLIPBOARD_RenderText(wFormat
);
911 if ( !lpRender
) return 0;
915 lpRender
= __lookup_format( ClipFormats
, wFormat
);
916 if( !lpRender
|| !CLIPBOARD_RenderFormat(lpRender
) ) return 0;
919 /* Convert between 32 -> 16 bit data, if necessary */
920 if( lpRender
->hData32
&& !lpRender
->hData16
921 && CLIPBOARD_IsMemoryObject(wFormat
) )
924 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
925 size
= sizeof( METAFILEPICT16
);
927 size
= GlobalSize(lpRender
->hData32
);
929 lpRender
->hData16
= GlobalAlloc16(GMEM_ZEROINIT
, size
);
930 if( !lpRender
->hData16
)
931 ERR("(%04X) -- not enough memory in 16b heap\n", wFormat
);
934 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
936 FIXME("\timplement function CopyMetaFilePict32to16\n");
937 FIXME("\tin the appropriate file.\n");
938 #ifdef SOMEONE_IMPLEMENTED_ME
939 CopyMetaFilePict32to16( GlobalLock16(lpRender
->hData16
),
940 GlobalLock(lpRender
->hData32
) );
945 memcpy( GlobalLock16(lpRender
->hData16
),
946 GlobalLock(lpRender
->hData32
),
949 GlobalUnlock16(lpRender
->hData16
);
950 GlobalUnlock(lpRender
->hData32
);
954 TRACE("\treturning %04x (type %i)\n",
955 lpRender
->hData16
, lpRender
->wFormatID
);
956 return lpRender
->hData16
;
960 /**************************************************************************
961 * GetClipboardData (USER32.222)
963 HANDLE WINAPI
GetClipboardData( UINT wFormat
)
965 LPWINE_CLIPFORMAT lpRender
= ClipFormats
;
967 TRACE("(%08X)\n", wFormat
);
969 if (CLIPBOARD_IsLocked())
971 WARN("Clipboard not opened by calling task!");
975 if( wFormat
== CF_UNICODETEXT
|| wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
)
977 lpRender
= CLIPBOARD_RenderText(wFormat
);
978 if ( !lpRender
) return 0;
982 lpRender
= __lookup_format( ClipFormats
, wFormat
);
983 if( !lpRender
|| !CLIPBOARD_RenderFormat(lpRender
) ) return 0;
986 /* Convert between 16 -> 32 bit data, if necessary */
987 if( lpRender
->hData16
&& !lpRender
->hData32
988 && CLIPBOARD_IsMemoryObject(wFormat
) )
991 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
992 size
= sizeof( METAFILEPICT
);
994 size
= GlobalSize16(lpRender
->hData16
);
995 lpRender
->hData32
= GlobalAlloc(GMEM_ZEROINIT
| GMEM_MOVEABLE
| GMEM_DDESHARE
,
997 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
999 FIXME("\timplement function CopyMetaFilePict16to32\n");
1000 FIXME("\tin the appropriate file.\n");
1001 #ifdef SOMEONE_IMPLEMENTED_ME
1002 CopyMetaFilePict16to32( GlobalLock16(lpRender
->hData32
),
1003 GlobalLock(lpRender
->hData16
) );
1008 memcpy( GlobalLock(lpRender
->hData32
),
1009 GlobalLock16(lpRender
->hData16
),
1012 GlobalUnlock(lpRender
->hData32
);
1013 GlobalUnlock16(lpRender
->hData16
);
1016 TRACE("\treturning %04x (type %i)\n",
1017 lpRender
->hData32
, lpRender
->wFormatID
);
1018 return lpRender
->hData32
;
1022 /**************************************************************************
1023 * CountClipboardFormats16 (USER.143)
1025 INT16 WINAPI
CountClipboardFormats16(void)
1027 return CountClipboardFormats();
1031 /**************************************************************************
1032 * CountClipboardFormats (USER32.63)
1034 INT WINAPI
CountClipboardFormats(void)
1036 INT FormatCount
= 0;
1037 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
1043 if (lpFormat
== NULL
) break;
1045 if( lpFormat
->wFormatID
!= CF_TEXT
) /* Don't count CF_TEXT */
1048 * The format is available if either:
1049 * 1. The data is already in the cache.
1050 * 2. The selection is not owned by us(WINE) and the data is
1051 * available to the clipboard driver.
1053 if ( lpFormat
->wDataPresent
||
1054 ( !USER_Driver
.pIsSelectionOwner()
1055 && USER_Driver
.pIsClipboardFormatAvailable( lpFormat
->wFormatID
) ) )
1057 TRACE("\tdata found for format 0x%04x(%s)\n",
1058 lpFormat
->wFormatID
, CLIPBOARD_GetFormatName(lpFormat
->wFormatID
));
1063 lpFormat
= lpFormat
->NextFormat
;
1066 /* these are equivalent, adjust the total */
1067 FormatCount
+= (ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
||
1068 ClipFormats
[CF_TEXT
-1].wDataPresent
||
1069 ClipFormats
[CF_OEMTEXT
-1].wDataPresent
) ? 1 : 0;
1071 TRACE("\ttotal %d\n", FormatCount
);
1076 /**************************************************************************
1077 * EnumClipboardFormats16 (USER.144)
1079 UINT16 WINAPI
EnumClipboardFormats16( UINT16 wFormat
)
1081 return EnumClipboardFormats( wFormat
);
1085 /**************************************************************************
1086 * EnumClipboardFormats (USER32.179)
1088 UINT WINAPI
EnumClipboardFormats( UINT wFormat
)
1090 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
1091 BOOL bFormatPresent
;
1093 TRACE("(%04X)\n", wFormat
);
1095 if (CLIPBOARD_IsLocked())
1097 WARN("Clipboard not opened by calling task!");
1101 if (wFormat
== 0) /* start from the beginning */
1102 lpFormat
= ClipFormats
;
1105 /* walk up to the specified format record */
1107 if( !(lpFormat
= __lookup_format( lpFormat
, wFormat
)) )
1109 lpFormat
= lpFormat
->NextFormat
; /* right */
1114 if (lpFormat
== NULL
) return 0;
1116 if(CLIPBOARD_IsPresent(lpFormat
->wFormatID
))
1119 /* Query the driver if not yet in the cache */
1120 if (!USER_Driver
.pIsSelectionOwner())
1122 if(lpFormat
->wFormatID
== CF_UNICODETEXT
||
1123 lpFormat
->wFormatID
== CF_TEXT
||
1124 lpFormat
->wFormatID
== CF_OEMTEXT
)
1126 if(USER_Driver
.pIsClipboardFormatAvailable(CF_UNICODETEXT
) ||
1127 USER_Driver
.pIsClipboardFormatAvailable(CF_TEXT
) ||
1128 USER_Driver
.pIsClipboardFormatAvailable(CF_OEMTEXT
))
1129 bFormatPresent
= TRUE
;
1131 bFormatPresent
= FALSE
;
1134 bFormatPresent
= USER_Driver
.pIsClipboardFormatAvailable(lpFormat
->wFormatID
);
1140 lpFormat
= lpFormat
->NextFormat
;
1143 TRACE("Next available format %d\n", lpFormat
->wFormatID
);
1145 return lpFormat
->wFormatID
;
1149 /**************************************************************************
1150 * RegisterClipboardFormat16 (USER.145)
1152 UINT16 WINAPI
RegisterClipboardFormat16( LPCSTR FormatName
)
1154 LPWINE_CLIPFORMAT lpNewFormat
;
1155 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
1157 if (FormatName
== NULL
) return 0;
1159 TRACE("('%s') !\n", FormatName
);
1161 /* walk format chain to see if it's already registered */
1165 if ( !strcmp(lpFormat
->Name
,FormatName
) )
1167 lpFormat
->wRefCount
++;
1168 return lpFormat
->wFormatID
;
1171 if ( lpFormat
->NextFormat
== NULL
) break;
1173 lpFormat
= lpFormat
->NextFormat
;
1176 /* allocate storage for new format entry */
1178 lpNewFormat
= (LPWINE_CLIPFORMAT
)HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_CLIPFORMAT
));
1179 if(lpNewFormat
== NULL
) {
1180 WARN("No more memory for a new format!");
1183 lpFormat
->NextFormat
= lpNewFormat
;
1184 lpNewFormat
->wFormatID
= LastRegFormat
;
1185 lpNewFormat
->wRefCount
= 1;
1187 lpNewFormat
->Name
= (LPSTR
)HEAP_strdupA(GetProcessHeap(), 0, FormatName
);
1188 if(lpNewFormat
->Name
== NULL
) {
1189 WARN("No more memory for the new format name!");
1190 HeapFree(GetProcessHeap(), 0, lpNewFormat
);
1194 lpNewFormat
->wDataPresent
= 0;
1195 lpNewFormat
->hData16
= 0;
1196 lpNewFormat
->hDataSrc32
= 0;
1197 lpNewFormat
->hData32
= 0;
1198 lpNewFormat
->drvData
= 0;
1199 lpNewFormat
->PrevFormat
= lpFormat
;
1200 lpNewFormat
->NextFormat
= NULL
;
1202 /* Pass on the registration request to the driver */
1203 USER_Driver
.pRegisterClipboardFormat( FormatName
);
1205 return LastRegFormat
++;
1209 /**************************************************************************
1210 * RegisterClipboardFormatA (USER32.431)
1212 UINT WINAPI
RegisterClipboardFormatA( LPCSTR formatName
)
1214 return RegisterClipboardFormat16( formatName
);
1218 /**************************************************************************
1219 * RegisterClipboardFormatW (USER32.432)
1221 UINT WINAPI
RegisterClipboardFormatW( LPCWSTR formatName
)
1223 LPSTR aFormat
= HEAP_strdupWtoA( GetProcessHeap(), 0, formatName
);
1224 UINT ret
= RegisterClipboardFormatA( aFormat
);
1225 HeapFree( GetProcessHeap(), 0, aFormat
);
1230 /**************************************************************************
1231 * GetClipboardFormatName16 (USER.146)
1233 INT16 WINAPI
GetClipboardFormatName16( UINT16 wFormat
, LPSTR retStr
, INT16 maxlen
)
1235 return GetClipboardFormatNameA( wFormat
, retStr
, maxlen
);
1239 /**************************************************************************
1240 * GetClipboardFormatNameA (USER32.223)
1242 INT WINAPI
GetClipboardFormatNameA( UINT wFormat
, LPSTR retStr
, INT maxlen
)
1244 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
1246 TRACE("(%04X, %p, %d) !\n", wFormat
, retStr
, maxlen
);
1248 if (lpFormat
== NULL
|| lpFormat
->Name
== NULL
||
1249 lpFormat
->wFormatID
< CF_REGFORMATBASE
) return 0;
1251 TRACE("Name='%s' !\n", lpFormat
->Name
);
1253 lstrcpynA( retStr
, lpFormat
->Name
, maxlen
);
1254 return strlen(retStr
);
1258 /**************************************************************************
1259 * GetClipboardFormatNameW (USER32.224)
1261 INT WINAPI
GetClipboardFormatNameW( UINT wFormat
, LPWSTR retStr
, INT maxlen
)
1264 LPSTR p
= HeapAlloc( GetProcessHeap(), 0, maxlen
);
1265 if(p
== NULL
) return 0; /* FIXME: is this the correct failure value? */
1267 ret
= GetClipboardFormatNameA( wFormat
, p
, maxlen
);
1269 if (maxlen
> 0 && !MultiByteToWideChar( CP_ACP
, 0, p
, -1, retStr
, maxlen
))
1270 retStr
[maxlen
-1] = 0;
1271 HeapFree( GetProcessHeap(), 0, p
);
1276 /**************************************************************************
1277 * SetClipboardViewer16 (USER.147)
1279 HWND16 WINAPI
SetClipboardViewer16( HWND16 hWnd
)
1281 TRACE("(%04x)\n", hWnd
);
1282 return SetClipboardViewer( hWnd
);
1286 /**************************************************************************
1287 * SetClipboardViewer (USER32.471)
1289 HWND WINAPI
SetClipboardViewer( HWND hWnd
)
1291 HWND hwndPrev
= hWndViewer
;
1293 TRACE("(%04x): returning %04x\n", hWnd
, hwndPrev
);
1300 /**************************************************************************
1301 * GetClipboardViewer16 (USER.148)
1303 HWND16 WINAPI
GetClipboardViewer16(void)
1310 /**************************************************************************
1311 * GetClipboardViewer (USER32.226)
1313 HWND WINAPI
GetClipboardViewer(void)
1320 /**************************************************************************
1321 * ChangeClipboardChain16 (USER.149)
1323 BOOL16 WINAPI
ChangeClipboardChain16(HWND16 hWnd
, HWND16 hWndNext
)
1325 return ChangeClipboardChain(hWnd
, hWndNext
);
1329 /**************************************************************************
1330 * ChangeClipboardChain (USER32.22)
1332 BOOL WINAPI
ChangeClipboardChain(HWND hWnd
, HWND hWndNext
)
1336 FIXME("(0x%04x, 0x%04x): stub?\n", hWnd
, hWndNext
);
1339 bRet
= !SendMessage16( hWndViewer
, WM_CHANGECBCHAIN
,
1340 (WPARAM16
)hWnd
, (LPARAM
)hWndNext
);
1342 WARN("hWndViewer is lost\n");
1344 if( hWnd
== hWndViewer
) hWndViewer
= hWndNext
;
1350 /**************************************************************************
1351 * IsClipboardFormatAvailable16 (USER.193)
1353 BOOL16 WINAPI
IsClipboardFormatAvailable16( UINT16 wFormat
)
1355 return IsClipboardFormatAvailable( wFormat
);
1359 /**************************************************************************
1360 * IsClipboardFormatAvailable (USER32.340)
1362 BOOL WINAPI
IsClipboardFormatAvailable( UINT wFormat
)
1366 if (wFormat
== 0) /* Reject this case quickly */
1369 bRet
= EnumClipboardFormats(wFormat
- 1) == wFormat
;
1371 TRACE("(%04X)- ret(%d)\n", wFormat
, bRet
);
1376 /**************************************************************************
1377 * GetOpenClipboardWindow16 (USER.248)
1378 * FIXME: This wont work if an external app owns the selection
1380 HWND16 WINAPI
GetOpenClipboardWindow16(void)
1383 return hWndClipWindow
;
1387 /**************************************************************************
1388 * GetOpenClipboardWindow (USER32.277)
1389 * FIXME: This wont work if an external app owns the selection
1391 HWND WINAPI
GetOpenClipboardWindow(void)
1394 return hWndClipWindow
;
1398 /**************************************************************************
1399 * GetPriorityClipboardFormat16 (USER.402)
1401 INT16 WINAPI
GetPriorityClipboardFormat16( UINT16
*lpPriorityList
, INT16 nCount
)
1403 FIXME("(%p,%d): stub\n", lpPriorityList
, nCount
);
1408 /**************************************************************************
1409 * GetPriorityClipboardFormat (USER32.279)
1411 INT WINAPI
GetPriorityClipboardFormat( UINT
*lpPriorityList
, INT nCount
)
1416 if(CountClipboardFormats() == 0)
1421 for(Counter
= 0; Counter
<= nCount
; Counter
++)
1423 if(IsClipboardFormatAvailable(*(lpPriorityList
+sizeof(INT
)*Counter
)))
1424 return *(lpPriorityList
+sizeof(INT
)*Counter
);
1431 /**************************************************************************
1432 * GetClipboardSequenceNumber (USER32)
1433 * Supported on Win2k/Win98
1434 * MSDN: Windows clipboard code keeps a serial number for the clipboard
1435 * for each window station. The number is incremented whenever the
1436 * contents change or are emptied.
1437 * If you do not have WINSTA_ACCESSCLIPBOARD then the function returns 0
1439 DWORD WINAPI
GetClipboardSequenceNumber(VOID
)
1441 FIXME("Returning 0, see windows/clipboard.c\n");
1442 /* FIXME: Use serial numbers */