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>
31 #include "wine/winuser16.h"
32 #include "wine/winbase16.h"
38 #include "clipboard.h"
39 #include "debugtools.h"
41 DEFAULT_DEBUG_CHANNEL(clipboard
);
43 #define CF_REGFORMATBASE 0xC000
45 /**************************************************************************
46 * Clipboard context global variables
49 static HANDLE hClipLock
= 0;
50 static BOOL bCBHasChanged
= FALSE
;
52 HWND hWndClipWindow
= 0; /* window that last opened clipboard */
53 HWND hWndClipOwner
= 0; /* current clipboard owner */
54 HANDLE16 hTaskClipOwner
= 0; /* clipboard owner's task */
55 static HWND hWndViewer
= 0; /* start of viewers chain */
57 static WORD LastRegFormat
= CF_REGFORMATBASE
;
59 /* Clipboard cache initial data.
60 * WARNING: This data ordering is dependent on the WINE_CLIPFORMAT structure
61 * declared in clipboard.h
63 WINE_CLIPFORMAT ClipFormats
[] = {
64 { CF_TEXT
, 1, 0, "Text", 0, 0, 0, 0, NULL
, &ClipFormats
[1]},
65 { CF_BITMAP
, 1, 0, "Bitmap", 0, 0, 0, 0, &ClipFormats
[0], &ClipFormats
[2]},
66 { CF_METAFILEPICT
, 1, 0, "MetaFile Picture", 0, 0, 0, 0, &ClipFormats
[1], &ClipFormats
[3]},
67 { CF_SYLK
, 1, 0, "Sylk", 0, 0, 0, 0, &ClipFormats
[2], &ClipFormats
[4]},
68 { CF_DIF
, 1, 0, "DIF", 0, 0, 0, 0, &ClipFormats
[3], &ClipFormats
[5]},
69 { CF_TIFF
, 1, 0, "TIFF", 0, 0, 0, 0, &ClipFormats
[4], &ClipFormats
[6]},
70 { CF_OEMTEXT
, 1, 0, "OEM Text", 0, 0, 0, 0, &ClipFormats
[5], &ClipFormats
[7]},
71 { CF_DIB
, 1, 0, "DIB", 0, 0, 0, 0, &ClipFormats
[6], &ClipFormats
[8]},
72 { CF_PALETTE
, 1, 0, "Palette", 0, 0, 0, 0, &ClipFormats
[7], &ClipFormats
[9]},
73 { CF_PENDATA
, 1, 0, "PenData", 0, 0, 0, 0, &ClipFormats
[8], &ClipFormats
[10]},
74 { CF_RIFF
, 1, 0, "RIFF", 0, 0, 0, 0, &ClipFormats
[9], &ClipFormats
[11]},
75 { CF_WAVE
, 1, 0, "Wave", 0, 0, 0, 0, &ClipFormats
[10], &ClipFormats
[12]},
76 { CF_UNICODETEXT
, 1, 0, "Unicode Text", 0, 0, 0, 0, &ClipFormats
[11], &ClipFormats
[13]},
77 { CF_OWNERDISPLAY
, 1, 0, "Owner Display", 0, 0, 0, 0, &ClipFormats
[12], &ClipFormats
[14]},
78 { CF_DSPTEXT
, 1, 0, "DSPText", 0, 0, 0, 0, &ClipFormats
[13], &ClipFormats
[15]},
79 { CF_DSPMETAFILEPICT
, 1, 0, "DSPMetaFile Picture", 0, 0, 0, 0, &ClipFormats
[14], &ClipFormats
[16]},
80 { CF_DSPBITMAP
, 1, 0, "DSPBitmap", 0, 0, 0, 0, &ClipFormats
[15], &ClipFormats
[17]},
81 { CF_HDROP
, 1, 0, "HDROP", 0, 0, 0, 0, &ClipFormats
[16], NULL
}
85 /**************************************************************************
86 * Internal Clipboard implementation methods
87 **************************************************************************/
90 /**************************************************************************
91 * CLIPBOARD_LookupFormat
93 static LPWINE_CLIPFORMAT
__lookup_format( LPWINE_CLIPFORMAT lpFormat
, WORD wID
)
97 if (lpFormat
== NULL
||
98 lpFormat
->wFormatID
== wID
) break;
99 lpFormat
= lpFormat
->NextFormat
;
104 LPWINE_CLIPFORMAT
CLIPBOARD_LookupFormat( WORD wID
)
106 return __lookup_format( ClipFormats
, wID
);
109 /**************************************************************************
111 * Check if the clipboard cache is available to the caller
113 BOOL
CLIPBOARD_IsLocked()
115 BOOL bIsLocked
= TRUE
;
116 HANDLE16 hTaskCur
= GetCurrentTask();
119 * The clipboard is available:
120 * 1. if the caller's task has opened the clipboard,
122 * 2. if the caller is the clipboard owners task, AND is responding to a
123 * WM_RENDERFORMAT message.
125 if ( hClipLock
== hTaskCur
)
128 else if ( hTaskCur
== hTaskClipOwner
)
130 /* Check if we're currently executing inside a window procedure
131 * called in response to a WM_RENDERFORMAT message. A WM_RENDERFORMAT
132 * handler is not permitted to open the clipboard since it has been opened
133 * by another client. However the handler must have access to the
134 * clipboard in order to update data in response to this message.
136 MESSAGEQUEUE
*queue
= QUEUE_Lock( GetFastQueue16() );
140 && queue
->smWaiting
->msg
== WM_RENDERFORMAT
141 && queue
->smWaiting
->hSrcQueue
145 QUEUE_Unlock( queue
);
151 /**************************************************************************
152 * CLIPBOARD_ReleaseOwner
153 * Gives up ownership of the clipboard
155 void CLIPBOARD_ReleaseOwner()
161 /**************************************************************************
162 * CLIPBOARD_GlobalFreeProc
164 * This is a callback mechanism to allow HGLOBAL data to be released in
165 * the context of the process which allocated it. We post a WM_TIMER message
166 * to the owner window(in CLIPBOARD_DeleteRecord) and destroy the data(in idEvent)
167 * in this WndProc, which is invoked when the apps message loop calls DispatchMessage.
168 * This technique is discussed in Matt Pietrek's "Under the Hood".
169 * An article describing the same may be found in MSDN by searching for WM_TIMER.
170 * Note that this mechanism will probably stop working when WINE supports
171 * address space separation. When "queue events" are implemented in Wine we
172 * should switch to using that mechanism, since it is more robust and does not
173 * require a procedure address to be passed. See the SetWinEventHook API for
176 VOID CALLBACK
CLIPBOARD_GlobalFreeProc( HWND hwnd
, UINT uMsg
, UINT idEvent
, DWORD dwTime
)
178 /* idEvent is the HGLOBAL to be deleted */
179 GlobalFree( (HGLOBAL
)idEvent
);
182 /**************************************************************************
183 * CLIPBOARD_DeleteRecord
185 void CLIPBOARD_DeleteRecord(LPWINE_CLIPFORMAT lpFormat
, BOOL bChange
)
187 if( (lpFormat
->wFormatID
>= CF_GDIOBJFIRST
&&
188 lpFormat
->wFormatID
<= CF_GDIOBJLAST
) || lpFormat
->wFormatID
== CF_BITMAP
189 || lpFormat
->wFormatID
== CF_PALETTE
)
191 if (lpFormat
->hData32
)
192 DeleteObject(lpFormat
->hData32
);
193 if (lpFormat
->hData16
)
194 DeleteObject(lpFormat
->hData16
);
196 else if( lpFormat
->wFormatID
== CF_METAFILEPICT
)
198 if (lpFormat
->hData32
)
200 DeleteMetaFile( ((METAFILEPICT
*)GlobalLock( lpFormat
->hData32
))->hMF
);
201 PostMessageA(hWndClipOwner
, WM_TIMER
,
202 (WPARAM
)lpFormat
->hData32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
203 if (lpFormat
->hDataSrc32
)
205 /* Release lpFormat->hData32 in the context of the process which created it.
206 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
207 * GlobalFree(lpFormat->hDataSrc32);
209 PostMessageA(hWndClipOwner
, WM_TIMER
,
210 (WPARAM
)lpFormat
->hDataSrc32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
213 if (lpFormat
->hData16
)
214 /* HMETAFILE16 and HMETAFILE32 are apparently the same thing,
215 and a shallow copy is enough to share a METAFILEPICT
216 structure between 16bit and 32bit clipboards. The MetaFile
217 should of course only be deleted once. */
218 GlobalFree16(lpFormat
->hData16
);
220 if (lpFormat
->hData16
)
222 DeleteMetaFile16( ((METAFILEPICT16
*)GlobalLock16( lpFormat
->hData16
))->hMF
);
223 GlobalFree16(lpFormat
->hData16
);
228 if (lpFormat
->hData32
)
230 /* Release lpFormat->hData32 in the context of the process which created it.
231 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
232 * GlobalFree( lpFormat->hData32 );
234 PostMessageA(hWndClipOwner
, WM_TIMER
,
235 (WPARAM
)lpFormat
->hData32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
237 if (lpFormat
->hDataSrc32
)
239 /* Release lpFormat->hData32 in the context of the process which created it.
240 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
241 * GlobalFree(lpFormat->hDataSrc32);
243 PostMessageA(hWndClipOwner
, WM_TIMER
,
244 (WPARAM
)lpFormat
->hDataSrc32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
246 if (lpFormat
->hData16
)
247 GlobalFree16(lpFormat
->hData16
);
250 lpFormat
->wDataPresent
= 0;
251 lpFormat
->hData16
= 0;
252 lpFormat
->hData32
= 0;
253 lpFormat
->hDataSrc32
= 0;
254 lpFormat
->drvData
= 0;
256 if( bChange
) bCBHasChanged
= TRUE
;
259 /**************************************************************************
260 * CLIPBOARD_EmptyCache
262 void CLIPBOARD_EmptyCache( BOOL bChange
)
264 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
268 if ( lpFormat
->wDataPresent
|| lpFormat
->hData16
|| lpFormat
->hData32
)
269 CLIPBOARD_DeleteRecord( lpFormat
, bChange
);
271 lpFormat
= lpFormat
->NextFormat
;
275 /**************************************************************************
276 * CLIPBOARD_IsPresent
278 BOOL
CLIPBOARD_IsPresent(WORD wFormat
)
282 if( wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
|| wFormat
== CF_UNICODETEXT
)
283 return ClipFormats
[CF_TEXT
-1].wDataPresent
||
284 ClipFormats
[CF_OEMTEXT
-1].wDataPresent
||
285 ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
;
288 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
289 if( lpFormat
) return (lpFormat
->wDataPresent
);
294 /**************************************************************************
295 * CLIPBOARD_IsCacheRendered
296 * Checks if any data needs to be rendered to the clipboard cache
298 * TRUE - All clipboard data is available in the cache
299 * FALSE - Some data is marked for delayed render and needs rendering
301 BOOL
CLIPBOARD_IsCacheRendered()
303 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
305 /* check if all formats were rendered */
308 if( lpFormat
->wDataPresent
&& !lpFormat
->hData16
&& !lpFormat
->hData32
)
311 lpFormat
= lpFormat
->NextFormat
;
318 /**************************************************************************
319 * CLIPBOARD_IsMemoryObject
320 * Tests if the clipboard format specifies a memory object
322 BOOL
CLIPBOARD_IsMemoryObject( WORD wFormat
)
327 case CF_METAFILEPICT
:
339 /***********************************************************************
340 * CLIPBOARD_GlobalDupMem( HGLOBAL )
341 * Helper method to duplicate an HGLOBAL chunk of memory into shared memory
343 HGLOBAL
CLIPBOARD_GlobalDupMem( HGLOBAL hGlobalSrc
)
346 PVOID pGlobalSrc
, pGlobalDest
;
352 cBytes
= GlobalSize(hGlobalSrc
);
356 /* Turn on the DDESHARE and _MOVEABLE flags explicitly */
357 hGlobalDest
= GlobalAlloc( GlobalFlags(hGlobalSrc
) | GMEM_DDESHARE
| GMEM_MOVEABLE
,
362 pGlobalSrc
= GlobalLock(hGlobalSrc
);
363 pGlobalDest
= GlobalLock(hGlobalDest
);
364 if ( !pGlobalSrc
|| !pGlobalDest
)
367 memcpy(pGlobalDest
, pGlobalSrc
, cBytes
);
369 GlobalUnlock(hGlobalSrc
);
370 GlobalUnlock(hGlobalDest
);
375 /**************************************************************************
376 * CLIPBOARD_GetFormatName
377 * Gets the format name associated with an ID
379 char * CLIPBOARD_GetFormatName(UINT wFormat
)
381 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
382 return (lpFormat
) ? lpFormat
->Name
: NULL
;
386 /**************************************************************************
387 * CLIPBOARD_RenderFormat
389 static BOOL
CLIPBOARD_RenderFormat(LPWINE_CLIPFORMAT lpFormat
)
392 * If WINE is not the selection owner, and the format is available
393 * we must ask the driver to render the data to the clipboard cache.
395 TRACE("enter format=%d\n", lpFormat
->wFormatID
);
396 if ( !USER_Driver
.pIsSelectionOwner()
397 && USER_Driver
.pIsClipboardFormatAvailable( lpFormat
->wFormatID
) )
399 if ( !USER_Driver
.pGetClipboardData( lpFormat
->wFormatID
) )
403 * If Wine owns the clipboard, and the data is marked for delayed render,
406 else if( lpFormat
->wDataPresent
&& !lpFormat
->hData16
&& !lpFormat
->hData32
)
408 if( IsWindow(hWndClipOwner
) )
410 /* Send a WM_RENDERFORMAT message to notify the owner to render the
411 * data requested into the clipboard.
413 TRACE("Sending WM_RENDERFORMAT message\n");
414 SendMessage16(hWndClipOwner
,WM_RENDERFORMAT
,
415 (WPARAM16
)lpFormat
->wFormatID
,0L);
419 WARN("\thWndClipOwner (%04x) is lost!\n",
421 CLIPBOARD_ReleaseOwner();
422 lpFormat
->wDataPresent
= 0;
427 return (lpFormat
->hData16
|| lpFormat
->hData32
) ? TRUE
: FALSE
;
430 /**************************************************************************
431 * CLIPBOARD_ConvertText
432 * Returns number of required/converted characters - not bytes!
434 static INT
CLIPBOARD_ConvertText(WORD src_fmt
, void const *src
, INT src_size
,
435 WORD dst_fmt
, void *dst
, INT dst_size
)
439 if(src_fmt
== CF_UNICODETEXT
)
452 return WideCharToMultiByte(cp
, 0, src
, src_size
, dst
, dst_size
, NULL
, NULL
);
455 if(dst_fmt
== CF_UNICODETEXT
)
468 return MultiByteToWideChar(cp
, 0, src
, src_size
, dst
, dst_size
);
471 if(!dst_size
) return src_size
;
473 if(dst_size
> src_size
) dst_size
= src_size
;
475 if(src_fmt
== CF_TEXT
)
476 CharToOemBuffA(src
, dst
, dst_size
);
478 OemToCharBuffA(src
, dst
, dst_size
);
483 /**************************************************************************
484 * CLIPBOARD_RenderText
486 * Renders text to the clipboard buffer converting between UNIX and DOS formats.
488 * RETURNS: pointer to the WINE_CLIPFORMAT if successful, NULL otherwise
490 * FIXME: Should be a pair of driver functions that convert between OEM text and Windows.
493 static LPWINE_CLIPFORMAT
CLIPBOARD_RenderText( UINT wFormat
)
495 LPWINE_CLIPFORMAT lpSource
= ClipFormats
;
496 LPWINE_CLIPFORMAT lpTarget
= NULL
;
497 BOOL foundData
= FALSE
;
499 /* Asked for CF_TEXT but not available - always attempt to convert
500 from CF_UNICODETEXT or CF_OEMTEXT */
501 if( wFormat
== CF_TEXT
&& !ClipFormats
[CF_TEXT
-1].wDataPresent
)
503 if(ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
)
505 /* Convert UNICODETEXT -> TEXT */
506 lpSource
= &ClipFormats
[CF_UNICODETEXT
-1];
507 lpTarget
= &ClipFormats
[CF_TEXT
-1];
509 TRACE("\tUNICODETEXT -> TEXT\n");
511 else if(ClipFormats
[CF_OEMTEXT
-1].wDataPresent
)
513 /* Convert OEMTEXT -> TEXT */
514 lpSource
= &ClipFormats
[CF_OEMTEXT
-1];
515 lpTarget
= &ClipFormats
[CF_TEXT
-1];
517 TRACE("\tOEMTEXT -> TEXT\n");
520 /* Asked for CF_OEMTEXT but not available - always attempt to convert
521 from CF_UNICODETEXT or CF_TEXT */
522 else if( wFormat
== CF_OEMTEXT
&& !ClipFormats
[CF_OEMTEXT
-1].wDataPresent
)
524 if(ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
)
526 /* Convert UNICODETEXT -> OEMTEXT */
527 lpSource
= &ClipFormats
[CF_UNICODETEXT
-1];
528 lpTarget
= &ClipFormats
[CF_OEMTEXT
-1];
530 TRACE("\tUNICODETEXT -> OEMTEXT\n");
532 else if(ClipFormats
[CF_TEXT
-1].wDataPresent
)
534 /* Convert TEXT -> OEMTEXT */
535 lpSource
= &ClipFormats
[CF_TEXT
-1];
536 lpTarget
= &ClipFormats
[CF_OEMTEXT
-1];
538 TRACE("\tTEXT -> OEMTEXT\n");
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");
564 if ((wFormat
== CF_TEXT
) || (wFormat
== CF_OEMTEXT
))
566 lpSource
= &ClipFormats
[CF_UNICODETEXT
-1];
567 lpTarget
= __lookup_format( ClipFormats
, wFormat
);
571 lpSource
= __lookup_format( ClipFormats
, wFormat
);
576 /* First render the source text format */
577 if ( !lpSource
|| !CLIPBOARD_RenderFormat(lpSource
) ) return NULL
;
579 /* Convert to the desired target text format, if necessary */
580 if( lpTarget
!= lpSource
&& !lpTarget
->hData16
&& !lpTarget
->hData32
)
582 INT src_chars
, dst_chars
, alloc_size
;
586 if (lpSource
->hData32
)
588 lpstrS
= (LPSTR
)GlobalLock(lpSource
->hData32
);
592 lpstrS
= (LPSTR
)GlobalLock16(lpSource
->hData16
);
595 if( !lpstrS
) return NULL
;
597 /* Text always NULL terminated */
598 if(lpSource
->wFormatID
== CF_UNICODETEXT
)
599 src_chars
= strlenW((LPCWSTR
)lpstrS
);
601 src_chars
= strlen(lpstrS
);
603 /* Calculate number of characters in the destination buffer */
604 dst_chars
= CLIPBOARD_ConvertText(lpSource
->wFormatID
, lpstrS
, src_chars
,
605 lpTarget
->wFormatID
, NULL
, 0);
606 if(!dst_chars
) return NULL
;
608 TRACE("\tconverting from '%s' to '%s', %i chars\n",
609 lpSource
->Name
, lpTarget
->Name
, src_chars
);
611 /* Convert characters to bytes */
612 if(lpTarget
->wFormatID
== CF_UNICODETEXT
)
613 alloc_size
= dst_chars
* sizeof(WCHAR
);
615 alloc_size
= dst_chars
;
617 lpTarget
->hData32
= GlobalAlloc(GMEM_ZEROINIT
| GMEM_MOVEABLE
| GMEM_DDESHARE
, alloc_size
);
618 lpstrT
= (LPSTR
)GlobalLock(lpTarget
->hData32
);
622 CLIPBOARD_ConvertText(lpSource
->wFormatID
, lpstrS
, src_chars
,
623 lpTarget
->wFormatID
, lpstrT
, dst_chars
);
624 GlobalUnlock(lpTarget
->hData32
);
627 lpTarget
->hData32
= 0;
630 if (lpSource
->hData32
)
631 GlobalUnlock(lpSource
->hData32
);
633 GlobalUnlock16(lpSource
->hData16
);
636 return (lpTarget
->hData16
|| lpTarget
->hData32
) ? lpTarget
: NULL
;
639 /**************************************************************************
640 * CLIPBOARD_EnumClipboardFormats (internal)
642 static UINT
CLIPBOARD_EnumClipboardFormats( UINT wFormat
)
644 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
647 if (wFormat
== 0) /* start from the beginning */
648 lpFormat
= ClipFormats
;
651 /* walk up to the specified format record */
653 if( !(lpFormat
= __lookup_format( lpFormat
, wFormat
)) )
655 lpFormat
= lpFormat
->NextFormat
; /* right */
660 if (lpFormat
== NULL
) return 0;
662 if(CLIPBOARD_IsPresent(lpFormat
->wFormatID
))
665 /* Query the driver if not yet in the cache */
666 if (!USER_Driver
.pIsSelectionOwner())
668 if(lpFormat
->wFormatID
== CF_UNICODETEXT
||
669 lpFormat
->wFormatID
== CF_TEXT
||
670 lpFormat
->wFormatID
== CF_OEMTEXT
)
672 if(USER_Driver
.pIsClipboardFormatAvailable(CF_UNICODETEXT
) ||
673 USER_Driver
.pIsClipboardFormatAvailable(CF_TEXT
) ||
674 USER_Driver
.pIsClipboardFormatAvailable(CF_OEMTEXT
))
675 bFormatPresent
= TRUE
;
677 bFormatPresent
= FALSE
;
680 bFormatPresent
= USER_Driver
.pIsClipboardFormatAvailable(lpFormat
->wFormatID
);
686 lpFormat
= lpFormat
->NextFormat
;
689 TRACE("Next available format %d\n", lpFormat
->wFormatID
);
691 return lpFormat
->wFormatID
;
695 /**************************************************************************
696 * WIN32 Clipboard implementation
697 **************************************************************************/
699 /**************************************************************************
700 * OpenClipboard (USER.137)
702 BOOL16 WINAPI
OpenClipboard16( HWND16 hWnd
)
704 return OpenClipboard( hWnd
);
708 /**************************************************************************
709 * OpenClipboard (USER32.@)
711 * Note: Netscape uses NULL hWnd to open the clipboard.
713 BOOL WINAPI
OpenClipboard( HWND hWnd
)
717 TRACE("(%04x)...\n", hWnd
);
721 hClipLock
= GetCurrentTask();
723 /* Save current user of the clipboard */
724 hWndClipWindow
= hWnd
;
725 bCBHasChanged
= FALSE
;
730 TRACE(" returning %i\n", bRet
);
735 /**************************************************************************
736 * CloseClipboard (USER.138)
738 BOOL16 WINAPI
CloseClipboard16(void)
740 return CloseClipboard();
744 /**************************************************************************
745 * CloseClipboard (USER32.@)
747 BOOL WINAPI
CloseClipboard(void)
751 if (hClipLock
== GetCurrentTask())
755 if (bCBHasChanged
&& hWndViewer
)
756 SendMessage16(hWndViewer
, WM_DRAWCLIPBOARD
, 0, 0L);
763 /**************************************************************************
764 * EmptyClipboard16 (USER.139)
766 BOOL16 WINAPI
EmptyClipboard16(void)
768 return EmptyClipboard();
772 /**************************************************************************
773 * EmptyClipboard (USER32.@)
774 * Empties and acquires ownership of the clipboard
776 BOOL WINAPI
EmptyClipboard(void)
780 if (hClipLock
!= GetCurrentTask())
782 WARN("Clipboard not opened by calling task!");
786 /* destroy private objects */
789 SendMessage16(hWndClipOwner
, WM_DESTROYCLIPBOARD
, 0, 0L);
791 /* empty the cache */
792 CLIPBOARD_EmptyCache(TRUE
);
794 /* Assign ownership of the clipboard to the current client */
795 hWndClipOwner
= hWndClipWindow
;
797 /* Save the current task */
798 hTaskClipOwner
= GetCurrentTask();
800 /* Tell the driver to acquire the selection */
801 USER_Driver
.pAcquireClipboard();
807 /**************************************************************************
808 * GetClipboardOwner (USER.140)
809 * FIXME: Can't return the owner if the clipbard is owned by an external app
811 HWND16 WINAPI
GetClipboardOwner16(void)
814 return hWndClipOwner
;
818 /**************************************************************************
819 * GetClipboardOwner (USER32.@)
820 * FIXME: Can't return the owner if the clipbard is owned by an external app
822 HWND WINAPI
GetClipboardOwner(void)
825 return hWndClipOwner
;
829 /**************************************************************************
830 * SetClipboardData (USER.141)
832 HANDLE16 WINAPI
SetClipboardData16( UINT16 wFormat
, HANDLE16 hData
)
834 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
836 TRACE("(%04X, %04x) !\n", wFormat
, hData
);
838 /* NOTE: If the hData is zero and current owner doesn't match
839 * the window that opened the clipboard then this application
840 * is screwed because WM_RENDERFORMAT will go to the owner.
841 * (to become the owner it must call EmptyClipboard() before
845 if( CLIPBOARD_IsLocked() || !lpFormat
||
846 (!hData
&& (!hWndClipOwner
|| (hWndClipOwner
!= hWndClipWindow
))) )
848 WARN("Invalid hData or clipboard not opened by calling task!\n");
852 /* Pass on the request to the driver */
853 USER_Driver
.pSetClipboardData(wFormat
);
855 if ( lpFormat
->wDataPresent
|| lpFormat
->hData16
|| lpFormat
->hData32
)
857 CLIPBOARD_DeleteRecord(lpFormat
, TRUE
);
859 /* delete existing CF_UNICODETEXT/CF_TEXT/CF_OEMTEXT aliases */
860 if(wFormat
== CF_UNICODETEXT
)
862 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
863 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
865 else if(wFormat
== CF_TEXT
)
867 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_UNICODETEXT
-1], TRUE
);
868 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
870 else if(wFormat
== CF_OEMTEXT
)
872 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_UNICODETEXT
-1], TRUE
);
873 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
877 bCBHasChanged
= TRUE
;
878 lpFormat
->wDataPresent
= 1;
879 lpFormat
->hData16
= hData
; /* 0 is legal, see WM_RENDERFORMAT */
880 lpFormat
->hData32
= 0;
882 return lpFormat
->hData16
;
886 /**************************************************************************
887 * SetClipboardData (USER32.@)
889 HANDLE WINAPI
SetClipboardData( UINT wFormat
, HANDLE hData
)
891 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
893 TRACE("(%08X, %08x) !\n", wFormat
, hData
);
895 /* NOTE: If the hData is zero and current owner doesn't match
896 * the window that opened the clipboard then this application
897 * is screwed because WM_RENDERFORMAT will go to the owner.
898 * (to become the owner it must call EmptyClipboard() before
902 if( CLIPBOARD_IsLocked() || !lpFormat
||
903 (!hData
&& (!hWndClipOwner
|| (hWndClipOwner
!= hWndClipWindow
))) )
905 WARN("Invalid hData or clipboard not opened by calling task!\n");
909 /* Tell the driver to acquire the selection */
910 USER_Driver
.pAcquireClipboard();
912 if ( lpFormat
->wDataPresent
&&
913 (lpFormat
->hData16
|| lpFormat
->hData32
) )
915 CLIPBOARD_DeleteRecord(lpFormat
, TRUE
);
917 /* delete existing CF_UNICODETEXT/CF_TEXT/CF_OEMTEXT aliases */
918 if(wFormat
== CF_UNICODETEXT
)
920 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
921 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
923 else if(wFormat
== CF_TEXT
)
925 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_UNICODETEXT
-1], TRUE
);
926 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
928 else if(wFormat
== CF_OEMTEXT
)
930 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_UNICODETEXT
-1], TRUE
);
931 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
935 bCBHasChanged
= TRUE
;
936 lpFormat
->wDataPresent
= 1;
937 lpFormat
->hDataSrc32
= hData
; /* Save the source handle */
940 * Make a shared duplicate if the memory is not shared
941 * TODO: What should be done for non-memory objects
943 if ( CLIPBOARD_IsMemoryObject(wFormat
) && hData
&& !(GlobalFlags(hData
) & GMEM_DDESHARE
) )
944 lpFormat
->hData32
= CLIPBOARD_GlobalDupMem( hData
);
946 lpFormat
->hData32
= hData
; /* 0 is legal, see WM_RENDERFORMAT */
948 lpFormat
->hData16
= 0;
950 return lpFormat
->hData32
; /* Should we return lpFormat->hDataSrc32 */
954 /**************************************************************************
955 * GetClipboardData (USER.142)
957 HANDLE16 WINAPI
GetClipboardData16( UINT16 wFormat
)
959 LPWINE_CLIPFORMAT lpRender
= ClipFormats
;
961 TRACE("(%04X)\n", wFormat
);
963 if (CLIPBOARD_IsLocked())
965 WARN("Clipboard not opened by calling task!\n");
969 if( wFormat
== CF_UNICODETEXT
|| wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
)
971 lpRender
= CLIPBOARD_RenderText(wFormat
);
972 if ( !lpRender
) return 0;
976 lpRender
= __lookup_format( ClipFormats
, wFormat
);
977 if( !lpRender
|| !CLIPBOARD_RenderFormat(lpRender
) ) return 0;
980 /* Convert between 32 -> 16 bit data, if necessary */
981 if( lpRender
->hData32
&& !lpRender
->hData16
982 && CLIPBOARD_IsMemoryObject(wFormat
) )
985 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
986 size
= sizeof( METAFILEPICT16
);
988 size
= GlobalSize(lpRender
->hData32
);
990 lpRender
->hData16
= GlobalAlloc16(GMEM_ZEROINIT
, size
);
991 if( !lpRender
->hData16
)
992 ERR("(%04X) -- not enough memory in 16b heap\n", wFormat
);
995 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
997 FIXME("\timplement function CopyMetaFilePict32to16\n");
998 FIXME("\tin the appropriate file.\n");
999 #ifdef SOMEONE_IMPLEMENTED_ME
1000 CopyMetaFilePict32to16( GlobalLock16(lpRender
->hData16
),
1001 GlobalLock(lpRender
->hData32
) );
1006 memcpy( GlobalLock16(lpRender
->hData16
),
1007 GlobalLock(lpRender
->hData32
),
1010 GlobalUnlock16(lpRender
->hData16
);
1011 GlobalUnlock(lpRender
->hData32
);
1015 TRACE("\treturning %04x (type %i)\n",
1016 lpRender
->hData16
, lpRender
->wFormatID
);
1017 return lpRender
->hData16
;
1021 /**************************************************************************
1022 * GetClipboardData (USER32.@)
1024 HANDLE WINAPI
GetClipboardData( UINT wFormat
)
1026 LPWINE_CLIPFORMAT lpRender
= ClipFormats
;
1028 TRACE("(%08X)\n", wFormat
);
1030 if (CLIPBOARD_IsLocked())
1032 WARN("Clipboard not opened by calling task!");
1036 if( wFormat
== CF_UNICODETEXT
|| wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
)
1038 lpRender
= CLIPBOARD_RenderText(wFormat
);
1039 if ( !lpRender
) return 0;
1043 lpRender
= __lookup_format( ClipFormats
, wFormat
);
1044 if( !lpRender
|| !CLIPBOARD_RenderFormat(lpRender
) ) return 0;
1047 /* Convert between 16 -> 32 bit data, if necessary */
1048 if( lpRender
->hData16
&& !lpRender
->hData32
1049 && CLIPBOARD_IsMemoryObject(wFormat
) )
1052 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
1053 size
= sizeof( METAFILEPICT
);
1055 size
= GlobalSize16(lpRender
->hData16
);
1056 lpRender
->hData32
= GlobalAlloc(GMEM_ZEROINIT
| GMEM_MOVEABLE
| GMEM_DDESHARE
,
1058 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
1060 FIXME("\timplement function CopyMetaFilePict16to32\n");
1061 FIXME("\tin the appropriate file.\n");
1062 #ifdef SOMEONE_IMPLEMENTED_ME
1063 CopyMetaFilePict16to32( GlobalLock16(lpRender
->hData32
),
1064 GlobalLock(lpRender
->hData16
) );
1069 memcpy( GlobalLock(lpRender
->hData32
),
1070 GlobalLock16(lpRender
->hData16
),
1073 GlobalUnlock(lpRender
->hData32
);
1074 GlobalUnlock16(lpRender
->hData16
);
1077 TRACE("\treturning %04x (type %i)\n",
1078 lpRender
->hData32
, lpRender
->wFormatID
);
1079 return lpRender
->hData32
;
1083 /**************************************************************************
1084 * CountClipboardFormats (USER.143)
1086 INT16 WINAPI
CountClipboardFormats16(void)
1088 return CountClipboardFormats();
1092 /**************************************************************************
1093 * CountClipboardFormats (USER32.@)
1095 INT WINAPI
CountClipboardFormats(void)
1097 INT FormatCount
= 0;
1098 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
1104 if (lpFormat
== NULL
) break;
1106 if( lpFormat
->wFormatID
!= CF_TEXT
) /* Don't count CF_TEXT */
1109 * The format is available if either:
1110 * 1. The data is already in the cache.
1111 * 2. The selection is not owned by us(WINE) and the data is
1112 * available to the clipboard driver.
1114 if ( lpFormat
->wDataPresent
||
1115 ( !USER_Driver
.pIsSelectionOwner()
1116 && USER_Driver
.pIsClipboardFormatAvailable( lpFormat
->wFormatID
) ) )
1118 TRACE("\tdata found for format 0x%04x(%s)\n",
1119 lpFormat
->wFormatID
, CLIPBOARD_GetFormatName(lpFormat
->wFormatID
));
1124 lpFormat
= lpFormat
->NextFormat
;
1127 /* these are equivalent, adjust the total */
1128 FormatCount
+= (ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
||
1129 ClipFormats
[CF_TEXT
-1].wDataPresent
||
1130 ClipFormats
[CF_OEMTEXT
-1].wDataPresent
) ? 1 : 0;
1132 TRACE("\ttotal %d\n", FormatCount
);
1136 /**************************************************************************
1137 * EnumClipboardFormats (USER.144)
1139 UINT16 WINAPI
EnumClipboardFormats16( UINT16 wFormat
)
1141 return EnumClipboardFormats( wFormat
);
1145 /**************************************************************************
1146 * EnumClipboardFormats (USER32.@)
1148 UINT WINAPI
EnumClipboardFormats( UINT wFormat
)
1150 TRACE("(%04X)\n", wFormat
);
1152 if (CLIPBOARD_IsLocked())
1154 WARN("Clipboard not opened by calling task!");
1158 return CLIPBOARD_EnumClipboardFormats(wFormat
);
1162 /**************************************************************************
1163 * RegisterClipboardFormat (USER.145)
1165 UINT16 WINAPI
RegisterClipboardFormat16( LPCSTR FormatName
)
1167 LPWINE_CLIPFORMAT lpNewFormat
;
1168 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
1170 if (FormatName
== NULL
) return 0;
1172 TRACE("('%s') !\n", FormatName
);
1174 /* walk format chain to see if it's already registered */
1178 if ( !strcmp(lpFormat
->Name
,FormatName
) )
1180 lpFormat
->wRefCount
++;
1181 return lpFormat
->wFormatID
;
1184 if ( lpFormat
->NextFormat
== NULL
) break;
1186 lpFormat
= lpFormat
->NextFormat
;
1189 /* allocate storage for new format entry */
1191 lpNewFormat
= (LPWINE_CLIPFORMAT
)HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_CLIPFORMAT
));
1192 if(lpNewFormat
== NULL
) {
1193 WARN("No more memory for a new format!");
1196 lpFormat
->NextFormat
= lpNewFormat
;
1197 lpNewFormat
->wFormatID
= LastRegFormat
;
1198 lpNewFormat
->wRefCount
= 1;
1200 lpNewFormat
->Name
= (LPSTR
)HEAP_strdupA(GetProcessHeap(), 0, FormatName
);
1201 if(lpNewFormat
->Name
== NULL
) {
1202 WARN("No more memory for the new format name!");
1203 HeapFree(GetProcessHeap(), 0, lpNewFormat
);
1207 lpNewFormat
->wDataPresent
= 0;
1208 lpNewFormat
->hData16
= 0;
1209 lpNewFormat
->hDataSrc32
= 0;
1210 lpNewFormat
->hData32
= 0;
1211 lpNewFormat
->drvData
= 0;
1212 lpNewFormat
->PrevFormat
= lpFormat
;
1213 lpNewFormat
->NextFormat
= NULL
;
1215 /* Pass on the registration request to the driver */
1216 USER_Driver
.pRegisterClipboardFormat( FormatName
);
1218 return LastRegFormat
++;
1222 /**************************************************************************
1223 * RegisterClipboardFormatA (USER32.@)
1225 UINT WINAPI
RegisterClipboardFormatA( LPCSTR formatName
)
1227 return RegisterClipboardFormat16( formatName
);
1231 /**************************************************************************
1232 * RegisterClipboardFormatW (USER32.@)
1234 UINT WINAPI
RegisterClipboardFormatW( LPCWSTR formatName
)
1236 LPSTR aFormat
= HEAP_strdupWtoA( GetProcessHeap(), 0, formatName
);
1237 UINT ret
= RegisterClipboardFormatA( aFormat
);
1238 HeapFree( GetProcessHeap(), 0, aFormat
);
1243 /**************************************************************************
1244 * GetClipboardFormatName (USER.146)
1246 INT16 WINAPI
GetClipboardFormatName16( UINT16 wFormat
, LPSTR retStr
, INT16 maxlen
)
1248 return GetClipboardFormatNameA( wFormat
, retStr
, maxlen
);
1252 /**************************************************************************
1253 * GetClipboardFormatNameA (USER32.@)
1255 INT WINAPI
GetClipboardFormatNameA( UINT wFormat
, LPSTR retStr
, INT maxlen
)
1257 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
1259 TRACE("(%04X, %p, %d) !\n", wFormat
, retStr
, maxlen
);
1261 if (lpFormat
== NULL
|| lpFormat
->Name
== NULL
||
1262 lpFormat
->wFormatID
< CF_REGFORMATBASE
) return 0;
1264 TRACE("Name='%s' !\n", lpFormat
->Name
);
1266 lstrcpynA( retStr
, lpFormat
->Name
, maxlen
);
1267 return strlen(retStr
);
1271 /**************************************************************************
1272 * GetClipboardFormatNameW (USER32.@)
1274 INT WINAPI
GetClipboardFormatNameW( UINT wFormat
, LPWSTR retStr
, INT maxlen
)
1277 LPSTR p
= HeapAlloc( GetProcessHeap(), 0, maxlen
);
1278 if(p
== NULL
) return 0; /* FIXME: is this the correct failure value? */
1280 ret
= GetClipboardFormatNameA( wFormat
, p
, maxlen
);
1282 if (maxlen
> 0 && !MultiByteToWideChar( CP_ACP
, 0, p
, -1, retStr
, maxlen
))
1283 retStr
[maxlen
-1] = 0;
1284 HeapFree( GetProcessHeap(), 0, p
);
1289 /**************************************************************************
1290 * SetClipboardViewer (USER.147)
1292 HWND16 WINAPI
SetClipboardViewer16( HWND16 hWnd
)
1294 TRACE("(%04x)\n", hWnd
);
1295 return SetClipboardViewer( hWnd
);
1299 /**************************************************************************
1300 * SetClipboardViewer (USER32.@)
1302 HWND WINAPI
SetClipboardViewer( HWND hWnd
)
1304 HWND hwndPrev
= hWndViewer
;
1306 TRACE("(%04x): returning %04x\n", hWnd
, hwndPrev
);
1313 /**************************************************************************
1314 * GetClipboardViewer (USER.148)
1316 HWND16 WINAPI
GetClipboardViewer16(void)
1323 /**************************************************************************
1324 * GetClipboardViewer (USER32.@)
1326 HWND WINAPI
GetClipboardViewer(void)
1333 /**************************************************************************
1334 * ChangeClipboardChain (USER.149)
1336 BOOL16 WINAPI
ChangeClipboardChain16(HWND16 hWnd
, HWND16 hWndNext
)
1338 return ChangeClipboardChain(hWnd
, hWndNext
);
1342 /**************************************************************************
1343 * ChangeClipboardChain (USER32.@)
1345 BOOL WINAPI
ChangeClipboardChain(HWND hWnd
, HWND hWndNext
)
1349 FIXME("(0x%04x, 0x%04x): stub?\n", hWnd
, hWndNext
);
1352 bRet
= !SendMessage16( hWndViewer
, WM_CHANGECBCHAIN
,
1353 (WPARAM16
)hWnd
, (LPARAM
)hWndNext
);
1355 WARN("hWndViewer is lost\n");
1357 if( hWnd
== hWndViewer
) hWndViewer
= hWndNext
;
1363 /**************************************************************************
1364 * IsClipboardFormatAvailable16 (USER.193)
1366 BOOL16 WINAPI
IsClipboardFormatAvailable16( UINT16 wFormat
)
1368 return IsClipboardFormatAvailable( wFormat
);
1372 /**************************************************************************
1373 * IsClipboardFormatAvailable (USER32.@)
1375 BOOL WINAPI
IsClipboardFormatAvailable( UINT wFormat
)
1379 if (wFormat
== 0) /* Reject this case quickly */
1383 UINT iret
= CLIPBOARD_EnumClipboardFormats(wFormat
- 1);
1384 if ((wFormat
== CF_TEXT
) || (wFormat
== CF_OEMTEXT
) || (wFormat
== CF_UNICODETEXT
))
1385 bRet
= ((iret
== CF_TEXT
) || (iret
== CF_OEMTEXT
) || (iret
== CF_UNICODETEXT
));
1387 bRet
= iret
== wFormat
;
1389 TRACE("(%04X)- ret(%d)\n", wFormat
, bRet
);
1394 /**************************************************************************
1395 * GetOpenClipboardWindow (USER.248)
1396 * FIXME: This wont work if an external app owns the selection
1398 HWND16 WINAPI
GetOpenClipboardWindow16(void)
1401 return hWndClipWindow
;
1405 /**************************************************************************
1406 * GetOpenClipboardWindow (USER32.@)
1407 * FIXME: This wont work if an external app owns the selection
1409 HWND WINAPI
GetOpenClipboardWindow(void)
1412 return hWndClipWindow
;
1416 /**************************************************************************
1417 * GetPriorityClipboardFormat (USER.402)
1419 INT16 WINAPI
GetPriorityClipboardFormat16( UINT16
*lpPriorityList
, INT16 nCount
)
1421 FIXME("(%p,%d): stub\n", lpPriorityList
, nCount
);
1426 /**************************************************************************
1427 * GetPriorityClipboardFormat (USER32.@)
1429 INT WINAPI
GetPriorityClipboardFormat( UINT
*lpPriorityList
, INT nCount
)
1434 if(CountClipboardFormats() == 0)
1439 for(Counter
= 0; Counter
<= nCount
; Counter
++)
1441 if(IsClipboardFormatAvailable(*(lpPriorityList
+sizeof(INT
)*Counter
)))
1442 return *(lpPriorityList
+sizeof(INT
)*Counter
);
1449 /**************************************************************************
1450 * GetClipboardSequenceNumber (USER32.@)
1451 * Supported on Win2k/Win98
1452 * MSDN: Windows clipboard code keeps a serial number for the clipboard
1453 * for each window station. The number is incremented whenever the
1454 * contents change or are emptied.
1455 * If you do not have WINSTA_ACCESSCLIPBOARD then the function returns 0
1457 DWORD WINAPI
GetClipboardSequenceNumber(VOID
)
1459 FIXME("Returning 0, see windows/clipboard.c\n");
1460 /* FIXME: Use serial numbers */