2 * WIN32 clipboard implementation
4 * Copyright 1994 Martin Ayotte
9 * This file contains the implementation for the WIN32 Clipboard API
10 * and Wine's internal clipboard cache.
11 * The actual contents of the clipboard are held in the clipboard cache.
12 * The internal implementation talks to a "clipboard driver" to fill or
13 * expose the cache to the native device. (Currently only the X11 and
14 * TTY clipboard driver are available)
21 #include <sys/types.h>
30 #include "wine/winuser16.h"
31 #include "wine/winbase16.h"
34 #include "clipboard.h"
35 #include "debugtools.h"
37 DEFAULT_DEBUG_CHANNEL(clipboard
);
39 #define CF_REGFORMATBASE 0xC000
41 /**************************************************************************
42 * Clipboard context global variables
45 static HANDLE hClipLock
= 0;
46 static BOOL bCBHasChanged
= FALSE
;
48 HWND hWndClipWindow
= 0; /* window that last opened clipboard */
49 HWND hWndClipOwner
= 0; /* current clipboard owner */
50 HANDLE16 hTaskClipOwner
= 0; /* clipboard owner's task */
51 static HWND hWndViewer
= 0; /* start of viewers chain */
53 static WORD LastRegFormat
= CF_REGFORMATBASE
;
55 /* Clipboard cache initial data.
56 * WARNING: This data ordering is dependent on the WINE_CLIPFORMAT structure
57 * declared in clipboard.h
59 WINE_CLIPFORMAT ClipFormats
[] = {
60 { CF_TEXT
, 1, 0, "Text", 0, 0, 0, 0, NULL
, &ClipFormats
[1]},
61 { CF_BITMAP
, 1, 0, "Bitmap", 0, 0, 0, 0, &ClipFormats
[0], &ClipFormats
[2]},
62 { CF_METAFILEPICT
, 1, 0, "MetaFile Picture", 0, 0, 0, 0, &ClipFormats
[1], &ClipFormats
[3]},
63 { CF_SYLK
, 1, 0, "Sylk", 0, 0, 0, 0, &ClipFormats
[2], &ClipFormats
[4]},
64 { CF_DIF
, 1, 0, "DIF", 0, 0, 0, 0, &ClipFormats
[3], &ClipFormats
[5]},
65 { CF_TIFF
, 1, 0, "TIFF", 0, 0, 0, 0, &ClipFormats
[4], &ClipFormats
[6]},
66 { CF_OEMTEXT
, 1, 0, "OEM Text", 0, 0, 0, 0, &ClipFormats
[5], &ClipFormats
[7]},
67 { CF_DIB
, 1, 0, "DIB", 0, 0, 0, 0, &ClipFormats
[6], &ClipFormats
[8]},
68 { CF_PALETTE
, 1, 0, "Palette", 0, 0, 0, 0, &ClipFormats
[7], &ClipFormats
[9]},
69 { CF_PENDATA
, 1, 0, "PenData", 0, 0, 0, 0, &ClipFormats
[8], &ClipFormats
[10]},
70 { CF_RIFF
, 1, 0, "RIFF", 0, 0, 0, 0, &ClipFormats
[9], &ClipFormats
[11]},
71 { CF_WAVE
, 1, 0, "Wave", 0, 0, 0, 0, &ClipFormats
[10], &ClipFormats
[12]},
72 { CF_UNICODETEXT
, 1, 0, "Unicode Text", 0, 0, 0, 0, &ClipFormats
[11], &ClipFormats
[13]},
73 { CF_OWNERDISPLAY
, 1, 0, "Owner Display", 0, 0, 0, 0, &ClipFormats
[12], &ClipFormats
[14]},
74 { CF_DSPTEXT
, 1, 0, "DSPText", 0, 0, 0, 0, &ClipFormats
[13], &ClipFormats
[15]},
75 { CF_DSPMETAFILEPICT
, 1, 0, "DSPMetaFile Picture", 0, 0, 0, 0, &ClipFormats
[14], &ClipFormats
[16]},
76 { CF_DSPBITMAP
, 1, 0, "DSPBitmap", 0, 0, 0, 0, &ClipFormats
[15], &ClipFormats
[17]},
77 { CF_HDROP
, 1, 0, "HDROP", 0, 0, 0, 0, &ClipFormats
[16], NULL
}
81 /**************************************************************************
82 * Internal Clipboard implementation methods
83 **************************************************************************/
86 /**************************************************************************
87 * CLIPBOARD_LookupFormat
89 static LPWINE_CLIPFORMAT
__lookup_format( LPWINE_CLIPFORMAT lpFormat
, WORD wID
)
93 if (lpFormat
== NULL
||
94 lpFormat
->wFormatID
== wID
) break;
95 lpFormat
= lpFormat
->NextFormat
;
100 LPWINE_CLIPFORMAT
CLIPBOARD_LookupFormat( WORD wID
)
102 return __lookup_format( ClipFormats
, wID
);
105 /**************************************************************************
107 * Check if the clipboard cache is available to the caller
109 BOOL
CLIPBOARD_IsLocked()
111 BOOL bIsLocked
= TRUE
;
112 HANDLE16 hTaskCur
= GetCurrentTask();
115 * The clipboard is available:
116 * 1. if the caller's task has opened the clipboard,
118 * 2. if the caller is the clipboard owners task, AND is responding to a
119 * WM_RENDERFORMAT message.
121 if ( hClipLock
== hTaskCur
)
124 else if ( hTaskCur
== hTaskClipOwner
)
126 /* Check if we're currently executing inside a window procedure
127 * called in response to a WM_RENDERFORMAT message. A WM_RENDERFORMAT
128 * handler is not permitted to open the clipboard since it has been opened
129 * by another client. However the handler must have access to the
130 * clipboard in order to update data in response to this message.
133 MESSAGEQUEUE
*queue
= QUEUE_Current();
137 && queue
->smWaiting
->msg
== WM_RENDERFORMAT
138 && queue
->smWaiting
->hSrcQueue
142 /* FIXME: queue check no longer possible */
150 /**************************************************************************
151 * CLIPBOARD_ReleaseOwner
152 * Gives up ownership of the clipboard
154 void CLIPBOARD_ReleaseOwner()
160 /**************************************************************************
161 * CLIPBOARD_GlobalFreeProc
163 * This is a callback mechanism to allow HGLOBAL data to be released in
164 * the context of the process which allocated it. We post a WM_TIMER message
165 * to the owner window(in CLIPBOARD_DeleteRecord) and destroy the data(in idEvent)
166 * in this WndProc, which is invoked when the apps message loop calls DispatchMessage.
167 * This technique is discussed in Matt Pietrek's "Under the Hood".
168 * An article describing the same may be found in MSDN by searching for WM_TIMER.
169 * Note that this mechanism will probably stop working when WINE supports
170 * address space separation. When "queue events" are implemented in Wine we
171 * should switch to using that mechanism, since it is more robust and does not
172 * require a procedure address to be passed. See the SetWinEventHook API for
175 VOID CALLBACK
CLIPBOARD_GlobalFreeProc( HWND hwnd
, UINT uMsg
, UINT idEvent
, DWORD dwTime
)
177 /* idEvent is the HGLOBAL to be deleted */
178 GlobalFree( (HGLOBAL
)idEvent
);
181 /**************************************************************************
182 * CLIPBOARD_DeleteRecord
184 void CLIPBOARD_DeleteRecord(LPWINE_CLIPFORMAT lpFormat
, BOOL bChange
)
186 if( (lpFormat
->wFormatID
>= CF_GDIOBJFIRST
&&
187 lpFormat
->wFormatID
<= CF_GDIOBJLAST
) || lpFormat
->wFormatID
== CF_BITMAP
188 || lpFormat
->wFormatID
== CF_PALETTE
)
190 if (lpFormat
->hData32
)
191 DeleteObject(lpFormat
->hData32
);
192 if (lpFormat
->hData16
)
193 DeleteObject(lpFormat
->hData16
);
195 else if( lpFormat
->wFormatID
== CF_METAFILEPICT
)
197 if (lpFormat
->hData32
)
199 DeleteMetaFile( ((METAFILEPICT
*)GlobalLock( lpFormat
->hData32
))->hMF
);
200 PostMessageA(hWndClipOwner
, WM_TIMER
,
201 (WPARAM
)lpFormat
->hData32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
202 if (lpFormat
->hDataSrc32
)
204 /* Release lpFormat->hData32 in the context of the process which created it.
205 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
206 * GlobalFree(lpFormat->hDataSrc32);
208 PostMessageA(hWndClipOwner
, WM_TIMER
,
209 (WPARAM
)lpFormat
->hDataSrc32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
212 if (lpFormat
->hData16
)
213 /* HMETAFILE16 and HMETAFILE32 are apparently the same thing,
214 and a shallow copy is enough to share a METAFILEPICT
215 structure between 16bit and 32bit clipboards. The MetaFile
216 should of course only be deleted once. */
217 GlobalFree16(lpFormat
->hData16
);
219 if (lpFormat
->hData16
)
221 DeleteMetaFile16( ((METAFILEPICT16
*)GlobalLock16( lpFormat
->hData16
))->hMF
);
222 GlobalFree16(lpFormat
->hData16
);
227 if (lpFormat
->hData32
)
229 /* Release lpFormat->hData32 in the context of the process which created it.
230 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
231 * GlobalFree( lpFormat->hData32 );
233 PostMessageA(hWndClipOwner
, WM_TIMER
,
234 (WPARAM
)lpFormat
->hData32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
236 if (lpFormat
->hDataSrc32
)
238 /* Release lpFormat->hData32 in the context of the process which created it.
239 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
240 * GlobalFree(lpFormat->hDataSrc32);
242 PostMessageA(hWndClipOwner
, WM_TIMER
,
243 (WPARAM
)lpFormat
->hDataSrc32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
245 if (lpFormat
->hData16
)
246 GlobalFree16(lpFormat
->hData16
);
249 lpFormat
->wDataPresent
= 0;
250 lpFormat
->hData16
= 0;
251 lpFormat
->hData32
= 0;
252 lpFormat
->hDataSrc32
= 0;
253 lpFormat
->drvData
= 0;
255 if( bChange
) bCBHasChanged
= TRUE
;
258 /**************************************************************************
259 * CLIPBOARD_EmptyCache
261 void CLIPBOARD_EmptyCache( BOOL bChange
)
263 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
267 if ( lpFormat
->wDataPresent
|| lpFormat
->hData16
|| lpFormat
->hData32
)
268 CLIPBOARD_DeleteRecord( lpFormat
, bChange
);
270 lpFormat
= lpFormat
->NextFormat
;
274 /**************************************************************************
275 * CLIPBOARD_IsPresent
277 BOOL
CLIPBOARD_IsPresent(WORD wFormat
)
281 if( wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
|| wFormat
== CF_UNICODETEXT
)
282 return ClipFormats
[CF_TEXT
-1].wDataPresent
||
283 ClipFormats
[CF_OEMTEXT
-1].wDataPresent
||
284 ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
;
287 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
288 if( lpFormat
) return (lpFormat
->wDataPresent
);
293 /**************************************************************************
294 * CLIPBOARD_IsCacheRendered
295 * Checks if any data needs to be rendered to the clipboard cache
297 * TRUE - All clipboard data is available in the cache
298 * FALSE - Some data is marked for delayed render and needs rendering
300 BOOL
CLIPBOARD_IsCacheRendered()
302 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
304 /* check if all formats were rendered */
307 if( lpFormat
->wDataPresent
&& !lpFormat
->hData16
&& !lpFormat
->hData32
)
310 lpFormat
= lpFormat
->NextFormat
;
317 /**************************************************************************
318 * CLIPBOARD_IsMemoryObject
319 * Tests if the clipboard format specifies a memory object
321 BOOL
CLIPBOARD_IsMemoryObject( WORD wFormat
)
326 case CF_METAFILEPICT
:
338 /***********************************************************************
339 * CLIPBOARD_GlobalDupMem( HGLOBAL )
340 * Helper method to duplicate an HGLOBAL chunk of memory into shared memory
342 HGLOBAL
CLIPBOARD_GlobalDupMem( HGLOBAL hGlobalSrc
)
345 PVOID pGlobalSrc
, pGlobalDest
;
351 cBytes
= GlobalSize(hGlobalSrc
);
355 /* Turn on the DDESHARE and _MOVEABLE flags explicitly */
356 hGlobalDest
= GlobalAlloc( GlobalFlags(hGlobalSrc
) | GMEM_DDESHARE
| GMEM_MOVEABLE
,
361 pGlobalSrc
= GlobalLock(hGlobalSrc
);
362 pGlobalDest
= GlobalLock(hGlobalDest
);
363 if ( !pGlobalSrc
|| !pGlobalDest
)
366 memcpy(pGlobalDest
, pGlobalSrc
, cBytes
);
368 GlobalUnlock(hGlobalSrc
);
369 GlobalUnlock(hGlobalDest
);
374 /**************************************************************************
375 * CLIPBOARD_GetFormatName
376 * Gets the format name associated with an ID
378 char * CLIPBOARD_GetFormatName(UINT wFormat
)
380 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
381 return (lpFormat
) ? lpFormat
->Name
: NULL
;
385 /**************************************************************************
386 * CLIPBOARD_RenderFormat
388 static BOOL
CLIPBOARD_RenderFormat(LPWINE_CLIPFORMAT lpFormat
)
391 * If WINE is not the selection owner, and the format is available
392 * we must ask the driver to render the data to the clipboard cache.
394 TRACE("enter format=%d\n", lpFormat
->wFormatID
);
395 if ( !USER_Driver
.pIsSelectionOwner()
396 && USER_Driver
.pIsClipboardFormatAvailable( lpFormat
->wFormatID
) )
398 if ( !USER_Driver
.pGetClipboardData( lpFormat
->wFormatID
) )
402 * If Wine owns the clipboard, and the data is marked for delayed render,
405 else if( lpFormat
->wDataPresent
&& !lpFormat
->hData16
&& !lpFormat
->hData32
)
407 if( IsWindow(hWndClipOwner
) )
409 /* Send a WM_RENDERFORMAT message to notify the owner to render the
410 * data requested into the clipboard.
412 TRACE("Sending WM_RENDERFORMAT message\n");
413 SendMessageW( hWndClipOwner
, WM_RENDERFORMAT
, (WPARAM
)lpFormat
->wFormatID
, 0 );
417 WARN("\thWndClipOwner (%04x) is lost!\n",
419 CLIPBOARD_ReleaseOwner();
420 lpFormat
->wDataPresent
= 0;
425 return (lpFormat
->hData16
|| lpFormat
->hData32
) ? TRUE
: FALSE
;
428 /**************************************************************************
429 * CLIPBOARD_ConvertText
430 * Returns number of required/converted characters - not bytes!
432 static INT
CLIPBOARD_ConvertText(WORD src_fmt
, void const *src
, INT src_size
,
433 WORD dst_fmt
, void *dst
, INT dst_size
)
437 if(src_fmt
== CF_UNICODETEXT
)
450 return WideCharToMultiByte(cp
, 0, src
, src_size
, dst
, dst_size
, NULL
, NULL
);
453 if(dst_fmt
== CF_UNICODETEXT
)
466 return MultiByteToWideChar(cp
, 0, src
, src_size
, dst
, dst_size
);
469 if(!dst_size
) return src_size
;
471 if(dst_size
> src_size
) dst_size
= src_size
;
473 if(src_fmt
== CF_TEXT
)
474 CharToOemBuffA(src
, dst
, dst_size
);
476 OemToCharBuffA(src
, dst
, dst_size
);
481 /**************************************************************************
482 * CLIPBOARD_RenderText
484 * Renders text to the clipboard buffer converting between UNIX and DOS formats.
486 * RETURNS: pointer to the WINE_CLIPFORMAT if successful, NULL otherwise
488 * FIXME: Should be a pair of driver functions that convert between OEM text and Windows.
491 static LPWINE_CLIPFORMAT
CLIPBOARD_RenderText( UINT wFormat
)
493 LPWINE_CLIPFORMAT lpSource
= ClipFormats
;
494 LPWINE_CLIPFORMAT lpTarget
= NULL
;
495 BOOL foundData
= FALSE
;
497 /* Asked for CF_TEXT */
498 if( wFormat
== CF_TEXT
)
500 if(ClipFormats
[CF_TEXT
-1].wDataPresent
)
502 lpSource
= &ClipFormats
[CF_TEXT
-1];
503 lpTarget
= &ClipFormats
[CF_TEXT
-1];
505 TRACE("\t TEXT -> TEXT\n");
507 else if(ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
)
509 /* Convert UNICODETEXT -> TEXT */
510 lpSource
= &ClipFormats
[CF_UNICODETEXT
-1];
511 lpTarget
= &ClipFormats
[CF_TEXT
-1];
513 TRACE("\tUNICODETEXT -> TEXT\n");
515 else if(ClipFormats
[CF_OEMTEXT
-1].wDataPresent
)
517 /* Convert OEMTEXT -> TEXT */
518 lpSource
= &ClipFormats
[CF_OEMTEXT
-1];
519 lpTarget
= &ClipFormats
[CF_TEXT
-1];
521 TRACE("\tOEMTEXT -> TEXT\n");
524 /* Asked for CF_OEMTEXT */
525 else if( wFormat
== CF_OEMTEXT
)
527 if(ClipFormats
[CF_OEMTEXT
-1].wDataPresent
)
529 lpSource
= &ClipFormats
[CF_OEMTEXT
-1];
530 lpTarget
= &ClipFormats
[CF_OEMTEXT
-1];
532 TRACE("\tOEMTEXT -> OEMTEXT\n");
534 else if(ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
)
536 /* Convert UNICODETEXT -> OEMTEXT */
537 lpSource
= &ClipFormats
[CF_UNICODETEXT
-1];
538 lpTarget
= &ClipFormats
[CF_OEMTEXT
-1];
540 TRACE("\tUNICODETEXT -> OEMTEXT\n");
542 else if(ClipFormats
[CF_TEXT
-1].wDataPresent
)
544 /* Convert TEXT -> OEMTEXT */
545 lpSource
= &ClipFormats
[CF_TEXT
-1];
546 lpTarget
= &ClipFormats
[CF_OEMTEXT
-1];
548 TRACE("\tTEXT -> OEMTEXT\n");
551 /* Asked for CF_UNICODETEXT */
552 else if( wFormat
== CF_UNICODETEXT
)
554 if(ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
)
556 lpSource
= &ClipFormats
[CF_UNICODETEXT
-1];
557 lpTarget
= &ClipFormats
[CF_UNICODETEXT
-1];
559 TRACE("\tUNICODETEXT -> UNICODETEXT\n");
561 else if(ClipFormats
[CF_TEXT
-1].wDataPresent
)
563 /* Convert TEXT -> UNICODETEXT */
564 lpSource
= &ClipFormats
[CF_TEXT
-1];
565 lpTarget
= &ClipFormats
[CF_UNICODETEXT
-1];
567 TRACE("\tTEXT -> UNICODETEXT\n");
569 else if(ClipFormats
[CF_OEMTEXT
-1].wDataPresent
)
571 /* Convert OEMTEXT -> UNICODETEXT */
572 lpSource
= &ClipFormats
[CF_OEMTEXT
-1];
573 lpTarget
= &ClipFormats
[CF_UNICODETEXT
-1];
575 TRACE("\tOEMTEXT -> UNICODETEXT\n");
580 if ((wFormat
== CF_TEXT
) || (wFormat
== CF_OEMTEXT
))
582 lpSource
= &ClipFormats
[CF_UNICODETEXT
-1];
583 lpTarget
= __lookup_format( ClipFormats
, wFormat
);
587 lpSource
= __lookup_format( ClipFormats
, wFormat
);
592 /* First render the source text format */
593 if ( !lpSource
|| !CLIPBOARD_RenderFormat(lpSource
) ) return NULL
;
595 /* Convert to the desired target text format, if necessary */
596 if( lpTarget
!= lpSource
&& !lpTarget
->hData16
&& !lpTarget
->hData32
)
598 INT src_chars
, dst_chars
, alloc_size
;
602 if (lpSource
->hData32
)
604 lpstrS
= (LPSTR
)GlobalLock(lpSource
->hData32
);
608 lpstrS
= (LPSTR
)GlobalLock16(lpSource
->hData16
);
611 if( !lpstrS
) return NULL
;
613 /* Text always NULL terminated */
614 if(lpSource
->wFormatID
== CF_UNICODETEXT
)
615 src_chars
= strlenW((LPCWSTR
)lpstrS
)+1;
617 src_chars
= strlen(lpstrS
)+1;
619 /* Calculate number of characters in the destination buffer */
620 dst_chars
= CLIPBOARD_ConvertText(lpSource
->wFormatID
, lpstrS
, src_chars
,
621 lpTarget
->wFormatID
, NULL
, 0);
622 if(!dst_chars
) return NULL
;
624 TRACE("\tconverting from '%s' to '%s', %i chars\n",
625 lpSource
->Name
, lpTarget
->Name
, src_chars
);
627 /* Convert characters to bytes */
628 if(lpTarget
->wFormatID
== CF_UNICODETEXT
)
629 alloc_size
= dst_chars
* sizeof(WCHAR
);
631 alloc_size
= dst_chars
;
633 lpTarget
->hData32
= GlobalAlloc(GMEM_ZEROINIT
| GMEM_MOVEABLE
| GMEM_DDESHARE
, alloc_size
);
634 lpstrT
= (LPSTR
)GlobalLock(lpTarget
->hData32
);
638 CLIPBOARD_ConvertText(lpSource
->wFormatID
, lpstrS
, src_chars
,
639 lpTarget
->wFormatID
, lpstrT
, dst_chars
);
640 GlobalUnlock(lpTarget
->hData32
);
643 lpTarget
->hData32
= 0;
646 if (lpSource
->hData32
)
647 GlobalUnlock(lpSource
->hData32
);
649 GlobalUnlock16(lpSource
->hData16
);
652 return (lpTarget
->hData16
|| lpTarget
->hData32
) ? lpTarget
: NULL
;
655 /**************************************************************************
656 * CLIPBOARD_EnumClipboardFormats (internal)
658 static UINT
CLIPBOARD_EnumClipboardFormats( UINT wFormat
)
660 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
663 if (wFormat
== 0) /* start from the beginning */
664 lpFormat
= ClipFormats
;
667 /* walk up to the specified format record */
669 if( !(lpFormat
= __lookup_format( lpFormat
, wFormat
)) )
671 lpFormat
= lpFormat
->NextFormat
; /* right */
676 if (lpFormat
== NULL
) return 0;
678 if(CLIPBOARD_IsPresent(lpFormat
->wFormatID
))
681 /* Query the driver if not yet in the cache */
682 if (!USER_Driver
.pIsSelectionOwner())
684 if(lpFormat
->wFormatID
== CF_UNICODETEXT
||
685 lpFormat
->wFormatID
== CF_TEXT
||
686 lpFormat
->wFormatID
== CF_OEMTEXT
)
688 if(USER_Driver
.pIsClipboardFormatAvailable(CF_UNICODETEXT
) ||
689 USER_Driver
.pIsClipboardFormatAvailable(CF_TEXT
) ||
690 USER_Driver
.pIsClipboardFormatAvailable(CF_OEMTEXT
))
691 bFormatPresent
= TRUE
;
693 bFormatPresent
= FALSE
;
696 bFormatPresent
= USER_Driver
.pIsClipboardFormatAvailable(lpFormat
->wFormatID
);
702 lpFormat
= lpFormat
->NextFormat
;
705 TRACE("Next available format %d\n", lpFormat
->wFormatID
);
707 return lpFormat
->wFormatID
;
711 /**************************************************************************
712 * WIN32 Clipboard implementation
713 **************************************************************************/
715 /**************************************************************************
716 * OpenClipboard (USER.137)
718 BOOL16 WINAPI
OpenClipboard16( HWND16 hWnd
)
720 return OpenClipboard( hWnd
);
724 /**************************************************************************
725 * OpenClipboard (USER32.@)
727 * Note: Netscape uses NULL hWnd to open the clipboard.
729 BOOL WINAPI
OpenClipboard( HWND hWnd
)
733 TRACE("(%04x)...\n", hWnd
);
737 hClipLock
= GetCurrentTask();
739 /* Save current user of the clipboard */
740 hWndClipWindow
= hWnd
;
741 bCBHasChanged
= FALSE
;
746 TRACE(" returning %i\n", bRet
);
751 /**************************************************************************
752 * CloseClipboard (USER.138)
754 BOOL16 WINAPI
CloseClipboard16(void)
756 return CloseClipboard();
760 /**************************************************************************
761 * CloseClipboard (USER32.@)
763 BOOL WINAPI
CloseClipboard(void)
767 if (hClipLock
== GetCurrentTask())
771 if (bCBHasChanged
&& hWndViewer
) SendMessageW( hWndViewer
, WM_DRAWCLIPBOARD
, 0, 0 );
778 /**************************************************************************
779 * EmptyClipboard (USER.139)
781 BOOL16 WINAPI
EmptyClipboard16(void)
783 return EmptyClipboard();
787 /**************************************************************************
788 * EmptyClipboard (USER32.@)
789 * Empties and acquires ownership of the clipboard
791 BOOL WINAPI
EmptyClipboard(void)
795 if (hClipLock
!= GetCurrentTask())
797 WARN("Clipboard not opened by calling task!\n");
801 /* destroy private objects */
803 if (hWndClipOwner
) SendMessageW( hWndClipOwner
, WM_DESTROYCLIPBOARD
, 0, 0 );
805 /* empty the cache */
806 CLIPBOARD_EmptyCache(TRUE
);
808 /* Assign ownership of the clipboard to the current client */
809 hWndClipOwner
= hWndClipWindow
;
811 /* Save the current task */
812 hTaskClipOwner
= GetCurrentTask();
814 /* Tell the driver to acquire the selection */
815 USER_Driver
.pAcquireClipboard();
821 /**************************************************************************
822 * GetClipboardOwner (USER.140)
823 * FIXME: Can't return the owner if the clipbard is owned by an external app
825 HWND16 WINAPI
GetClipboardOwner16(void)
828 return hWndClipOwner
;
832 /**************************************************************************
833 * GetClipboardOwner (USER32.@)
834 * FIXME: Can't return the owner if the clipbard is owned by an external app
836 HWND WINAPI
GetClipboardOwner(void)
839 return hWndClipOwner
;
843 /**************************************************************************
844 * SetClipboardData (USER.141)
846 HANDLE16 WINAPI
SetClipboardData16( UINT16 wFormat
, HANDLE16 hData
)
848 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
850 TRACE("(%04X, %04x) !\n", wFormat
, hData
);
852 /* NOTE: If the hData is zero and current owner doesn't match
853 * the window that opened the clipboard then this application
854 * is screwed because WM_RENDERFORMAT will go to the owner.
855 * (to become the owner it must call EmptyClipboard() before
859 if( CLIPBOARD_IsLocked() || !lpFormat
||
860 (!hData
&& (!hWndClipOwner
|| (hWndClipOwner
!= hWndClipWindow
))) )
862 WARN("Invalid hData or clipboard not opened by calling task!\n");
866 /* Pass on the request to the driver */
867 USER_Driver
.pSetClipboardData(wFormat
);
869 if ( lpFormat
->wDataPresent
|| lpFormat
->hData16
|| lpFormat
->hData32
)
871 CLIPBOARD_DeleteRecord(lpFormat
, TRUE
);
873 /* delete existing CF_UNICODETEXT/CF_TEXT/CF_OEMTEXT aliases */
874 if(wFormat
== CF_UNICODETEXT
)
876 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
877 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
879 else if(wFormat
== CF_TEXT
)
881 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_UNICODETEXT
-1], TRUE
);
882 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
884 else if(wFormat
== CF_OEMTEXT
)
886 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_UNICODETEXT
-1], TRUE
);
887 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
891 bCBHasChanged
= TRUE
;
892 lpFormat
->wDataPresent
= 1;
893 lpFormat
->hData16
= hData
; /* 0 is legal, see WM_RENDERFORMAT */
894 lpFormat
->hData32
= 0;
896 return lpFormat
->hData16
;
900 /**************************************************************************
901 * SetClipboardData (USER32.@)
903 HANDLE WINAPI
SetClipboardData( UINT wFormat
, HANDLE hData
)
905 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
907 TRACE("(%08X, %08x) !\n", wFormat
, hData
);
909 /* NOTE: If the hData is zero and current owner doesn't match
910 * the window that opened the clipboard then this application
911 * is screwed because WM_RENDERFORMAT will go to the owner.
912 * (to become the owner it must call EmptyClipboard() before
916 if( CLIPBOARD_IsLocked() || !lpFormat
||
917 (!hData
&& (!hWndClipOwner
|| (hWndClipOwner
!= hWndClipWindow
))) )
919 WARN("Invalid hData or clipboard not opened by calling task!\n");
923 /* Tell the driver to acquire the selection */
924 USER_Driver
.pAcquireClipboard();
926 if ( lpFormat
->wDataPresent
&&
927 (lpFormat
->hData16
|| lpFormat
->hData32
) )
929 CLIPBOARD_DeleteRecord(lpFormat
, TRUE
);
931 /* delete existing CF_UNICODETEXT/CF_TEXT/CF_OEMTEXT aliases */
932 if(wFormat
== CF_UNICODETEXT
)
934 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
935 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
937 else if(wFormat
== CF_TEXT
)
939 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_UNICODETEXT
-1], TRUE
);
940 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
942 else if(wFormat
== CF_OEMTEXT
)
944 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_UNICODETEXT
-1], TRUE
);
945 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
949 bCBHasChanged
= TRUE
;
950 lpFormat
->wDataPresent
= 1;
951 lpFormat
->hDataSrc32
= hData
; /* Save the source handle */
954 * Make a shared duplicate if the memory is not shared
955 * TODO: What should be done for non-memory objects
957 if ( CLIPBOARD_IsMemoryObject(wFormat
) && hData
&& !(GlobalFlags(hData
) & GMEM_DDESHARE
) )
958 lpFormat
->hData32
= CLIPBOARD_GlobalDupMem( hData
);
960 lpFormat
->hData32
= hData
; /* 0 is legal, see WM_RENDERFORMAT */
962 lpFormat
->hData16
= 0;
964 return lpFormat
->hData32
; /* Should we return lpFormat->hDataSrc32 */
968 /**************************************************************************
969 * GetClipboardData (USER.142)
971 HANDLE16 WINAPI
GetClipboardData16( UINT16 wFormat
)
973 LPWINE_CLIPFORMAT lpRender
= ClipFormats
;
975 TRACE("(%04X)\n", wFormat
);
977 if (CLIPBOARD_IsLocked())
979 WARN("Clipboard not opened by calling task!\n");
983 if( wFormat
== CF_UNICODETEXT
|| wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
)
985 lpRender
= CLIPBOARD_RenderText(wFormat
);
986 if ( !lpRender
) return 0;
990 lpRender
= __lookup_format( ClipFormats
, wFormat
);
991 if( !lpRender
|| !CLIPBOARD_RenderFormat(lpRender
) ) return 0;
994 /* Convert between 32 -> 16 bit data, if necessary */
995 if( lpRender
->hData32
&& !lpRender
->hData16
996 && CLIPBOARD_IsMemoryObject(wFormat
) )
999 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
1000 size
= sizeof( METAFILEPICT16
);
1002 size
= GlobalSize(lpRender
->hData32
);
1004 lpRender
->hData16
= GlobalAlloc16(GMEM_ZEROINIT
, size
);
1005 if( !lpRender
->hData16
)
1006 ERR("(%04X) -- not enough memory in 16b heap\n", wFormat
);
1009 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
1011 FIXME("\timplement function CopyMetaFilePict32to16\n");
1012 FIXME("\tin the appropriate file.\n");
1013 #ifdef SOMEONE_IMPLEMENTED_ME
1014 CopyMetaFilePict32to16( GlobalLock16(lpRender
->hData16
),
1015 GlobalLock(lpRender
->hData32
) );
1020 memcpy( GlobalLock16(lpRender
->hData16
),
1021 GlobalLock(lpRender
->hData32
),
1024 GlobalUnlock16(lpRender
->hData16
);
1025 GlobalUnlock(lpRender
->hData32
);
1029 TRACE("\treturning %04x (type %i)\n",
1030 lpRender
->hData16
, lpRender
->wFormatID
);
1031 return lpRender
->hData16
;
1035 /**************************************************************************
1036 * GetClipboardData (USER32.@)
1038 HANDLE WINAPI
GetClipboardData( UINT wFormat
)
1040 LPWINE_CLIPFORMAT lpRender
= ClipFormats
;
1042 TRACE("(%08X)\n", wFormat
);
1044 if (CLIPBOARD_IsLocked())
1046 WARN("Clipboard not opened by calling task!\n");
1050 if( wFormat
== CF_UNICODETEXT
|| wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
)
1052 lpRender
= CLIPBOARD_RenderText(wFormat
);
1053 if ( !lpRender
) return 0;
1057 lpRender
= __lookup_format( ClipFormats
, wFormat
);
1058 if( !lpRender
|| !CLIPBOARD_RenderFormat(lpRender
) ) return 0;
1061 /* Convert between 16 -> 32 bit data, if necessary */
1062 if( lpRender
->hData16
&& !lpRender
->hData32
1063 && CLIPBOARD_IsMemoryObject(wFormat
) )
1066 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
1067 size
= sizeof( METAFILEPICT
);
1069 size
= GlobalSize16(lpRender
->hData16
);
1070 lpRender
->hData32
= GlobalAlloc(GMEM_ZEROINIT
| GMEM_MOVEABLE
| GMEM_DDESHARE
,
1072 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
1074 FIXME("\timplement function CopyMetaFilePict16to32\n");
1075 FIXME("\tin the appropriate file.\n");
1076 #ifdef SOMEONE_IMPLEMENTED_ME
1077 CopyMetaFilePict16to32( GlobalLock16(lpRender
->hData32
),
1078 GlobalLock(lpRender
->hData16
) );
1083 memcpy( GlobalLock(lpRender
->hData32
),
1084 GlobalLock16(lpRender
->hData16
),
1087 GlobalUnlock(lpRender
->hData32
);
1088 GlobalUnlock16(lpRender
->hData16
);
1091 TRACE("\treturning %04x (type %i)\n",
1092 lpRender
->hData32
, lpRender
->wFormatID
);
1093 return lpRender
->hData32
;
1097 /**************************************************************************
1098 * CountClipboardFormats (USER.143)
1100 INT16 WINAPI
CountClipboardFormats16(void)
1102 return CountClipboardFormats();
1106 /**************************************************************************
1107 * CountClipboardFormats (USER32.@)
1109 INT WINAPI
CountClipboardFormats(void)
1111 INT FormatCount
= 0;
1112 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
1118 if (lpFormat
== NULL
) break;
1120 if( lpFormat
->wFormatID
!= CF_TEXT
) /* Don't count CF_TEXT */
1123 * The format is available if either:
1124 * 1. The data is already in the cache.
1125 * 2. The selection is not owned by us(WINE) and the data is
1126 * available to the clipboard driver.
1128 if ( lpFormat
->wDataPresent
||
1129 ( !USER_Driver
.pIsSelectionOwner()
1130 && USER_Driver
.pIsClipboardFormatAvailable( lpFormat
->wFormatID
) ) )
1132 TRACE("\tdata found for format 0x%04x(%s)\n",
1133 lpFormat
->wFormatID
, CLIPBOARD_GetFormatName(lpFormat
->wFormatID
));
1138 lpFormat
= lpFormat
->NextFormat
;
1141 /* these are equivalent, adjust the total */
1142 FormatCount
+= (ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
||
1143 ClipFormats
[CF_TEXT
-1].wDataPresent
||
1144 ClipFormats
[CF_OEMTEXT
-1].wDataPresent
) ? 1 : 0;
1146 TRACE("\ttotal %d\n", FormatCount
);
1150 /**************************************************************************
1151 * EnumClipboardFormats (USER.144)
1153 UINT16 WINAPI
EnumClipboardFormats16( UINT16 wFormat
)
1155 return EnumClipboardFormats( wFormat
);
1159 /**************************************************************************
1160 * EnumClipboardFormats (USER32.@)
1162 UINT WINAPI
EnumClipboardFormats( UINT wFormat
)
1164 TRACE("(%04X)\n", wFormat
);
1166 if (CLIPBOARD_IsLocked())
1168 WARN("Clipboard not opened by calling task!\n");
1172 return CLIPBOARD_EnumClipboardFormats(wFormat
);
1176 /**************************************************************************
1177 * RegisterClipboardFormatA (USER32.@)
1179 UINT WINAPI
RegisterClipboardFormatA( LPCSTR FormatName
)
1181 LPWINE_CLIPFORMAT lpNewFormat
;
1182 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
1184 if (FormatName
== NULL
) return 0;
1186 TRACE("('%s') !\n", FormatName
);
1188 /* walk format chain to see if it's already registered */
1192 if ( !strcmp(lpFormat
->Name
,FormatName
) )
1194 lpFormat
->wRefCount
++;
1195 return lpFormat
->wFormatID
;
1198 if ( lpFormat
->NextFormat
== NULL
) break;
1200 lpFormat
= lpFormat
->NextFormat
;
1203 /* allocate storage for new format entry */
1205 lpNewFormat
= (LPWINE_CLIPFORMAT
)HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_CLIPFORMAT
));
1206 if(lpNewFormat
== NULL
) {
1207 WARN("No more memory for a new format!\n");
1210 lpFormat
->NextFormat
= lpNewFormat
;
1211 lpNewFormat
->wFormatID
= LastRegFormat
;
1212 lpNewFormat
->wRefCount
= 1;
1214 if (!(lpNewFormat
->Name
= HeapAlloc(GetProcessHeap(), 0, strlen(FormatName
)+1 )))
1216 WARN("No more memory for the new format name!\n");
1217 HeapFree(GetProcessHeap(), 0, lpNewFormat
);
1220 strcpy( lpNewFormat
->Name
, FormatName
);
1222 lpNewFormat
->wDataPresent
= 0;
1223 lpNewFormat
->hData16
= 0;
1224 lpNewFormat
->hDataSrc32
= 0;
1225 lpNewFormat
->hData32
= 0;
1226 lpNewFormat
->drvData
= 0;
1227 lpNewFormat
->PrevFormat
= lpFormat
;
1228 lpNewFormat
->NextFormat
= NULL
;
1230 /* Pass on the registration request to the driver */
1231 USER_Driver
.pRegisterClipboardFormat( FormatName
);
1233 return LastRegFormat
++;
1237 /**************************************************************************
1238 * RegisterClipboardFormat (USER.145)
1240 UINT16 WINAPI
RegisterClipboardFormat16( LPCSTR FormatName
)
1242 return RegisterClipboardFormatA( FormatName
);
1246 /**************************************************************************
1247 * RegisterClipboardFormatW (USER32.@)
1249 UINT WINAPI
RegisterClipboardFormatW( LPCWSTR formatName
)
1251 LPSTR aFormat
= HEAP_strdupWtoA( GetProcessHeap(), 0, formatName
);
1252 UINT ret
= RegisterClipboardFormatA( aFormat
);
1253 HeapFree( GetProcessHeap(), 0, aFormat
);
1258 /**************************************************************************
1259 * GetClipboardFormatName (USER.146)
1261 INT16 WINAPI
GetClipboardFormatName16( UINT16 wFormat
, LPSTR retStr
, INT16 maxlen
)
1263 return GetClipboardFormatNameA( wFormat
, retStr
, maxlen
);
1267 /**************************************************************************
1268 * GetClipboardFormatNameA (USER32.@)
1270 INT WINAPI
GetClipboardFormatNameA( UINT wFormat
, LPSTR retStr
, INT maxlen
)
1272 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
1274 TRACE("(%04X, %p, %d) !\n", wFormat
, retStr
, maxlen
);
1276 if (lpFormat
== NULL
|| lpFormat
->Name
== NULL
||
1277 lpFormat
->wFormatID
< CF_REGFORMATBASE
) return 0;
1279 TRACE("Name='%s' !\n", lpFormat
->Name
);
1281 lstrcpynA( retStr
, lpFormat
->Name
, maxlen
);
1282 return strlen(retStr
);
1286 /**************************************************************************
1287 * GetClipboardFormatNameW (USER32.@)
1289 INT WINAPI
GetClipboardFormatNameW( UINT wFormat
, LPWSTR retStr
, INT maxlen
)
1292 LPSTR p
= HeapAlloc( GetProcessHeap(), 0, maxlen
);
1293 if(p
== NULL
) return 0; /* FIXME: is this the correct failure value? */
1295 ret
= GetClipboardFormatNameA( wFormat
, p
, maxlen
);
1297 if (maxlen
> 0 && !MultiByteToWideChar( CP_ACP
, 0, p
, -1, retStr
, maxlen
))
1298 retStr
[maxlen
-1] = 0;
1299 HeapFree( GetProcessHeap(), 0, p
);
1304 /**************************************************************************
1305 * SetClipboardViewer (USER.147)
1307 HWND16 WINAPI
SetClipboardViewer16( HWND16 hWnd
)
1309 TRACE("(%04x)\n", hWnd
);
1310 return SetClipboardViewer( hWnd
);
1314 /**************************************************************************
1315 * SetClipboardViewer (USER32.@)
1317 HWND WINAPI
SetClipboardViewer( HWND hWnd
)
1319 HWND hwndPrev
= hWndViewer
;
1321 TRACE("(%04x): returning %04x\n", hWnd
, hwndPrev
);
1328 /**************************************************************************
1329 * GetClipboardViewer (USER.148)
1331 HWND16 WINAPI
GetClipboardViewer16(void)
1338 /**************************************************************************
1339 * GetClipboardViewer (USER32.@)
1341 HWND WINAPI
GetClipboardViewer(void)
1348 /**************************************************************************
1349 * ChangeClipboardChain (USER.149)
1351 BOOL16 WINAPI
ChangeClipboardChain16(HWND16 hWnd
, HWND16 hWndNext
)
1353 return ChangeClipboardChain(hWnd
, hWndNext
);
1357 /**************************************************************************
1358 * ChangeClipboardChain (USER32.@)
1360 BOOL WINAPI
ChangeClipboardChain(HWND hWnd
, HWND hWndNext
)
1364 FIXME("(0x%04x, 0x%04x): stub?\n", hWnd
, hWndNext
);
1367 bRet
= !SendMessageW( hWndViewer
, WM_CHANGECBCHAIN
, (WPARAM
)hWnd
, (LPARAM
)hWndNext
);
1369 WARN("hWndViewer is lost\n");
1371 if( hWnd
== hWndViewer
) hWndViewer
= hWndNext
;
1377 /**************************************************************************
1378 * IsClipboardFormatAvailable (USER.193)
1380 BOOL16 WINAPI
IsClipboardFormatAvailable16( UINT16 wFormat
)
1382 return IsClipboardFormatAvailable( wFormat
);
1386 /**************************************************************************
1387 * IsClipboardFormatAvailable (USER32.@)
1389 BOOL WINAPI
IsClipboardFormatAvailable( UINT wFormat
)
1393 if (wFormat
== 0) /* Reject this case quickly */
1397 UINT iret
= CLIPBOARD_EnumClipboardFormats(wFormat
- 1);
1398 if ((wFormat
== CF_TEXT
) || (wFormat
== CF_OEMTEXT
) || (wFormat
== CF_UNICODETEXT
))
1399 bRet
= ((iret
== CF_TEXT
) || (iret
== CF_OEMTEXT
) || (iret
== CF_UNICODETEXT
));
1401 bRet
= iret
== wFormat
;
1403 TRACE("(%04X)- ret(%d)\n", wFormat
, bRet
);
1408 /**************************************************************************
1409 * GetOpenClipboardWindow (USER.248)
1410 * FIXME: This wont work if an external app owns the selection
1412 HWND16 WINAPI
GetOpenClipboardWindow16(void)
1415 return hWndClipWindow
;
1419 /**************************************************************************
1420 * GetOpenClipboardWindow (USER32.@)
1421 * FIXME: This wont work if an external app owns the selection
1423 HWND WINAPI
GetOpenClipboardWindow(void)
1426 return hWndClipWindow
;
1430 /**************************************************************************
1431 * GetPriorityClipboardFormat (USER.402)
1433 INT16 WINAPI
GetPriorityClipboardFormat16( UINT16
*lpPriorityList
, INT16 nCount
)
1435 FIXME("(%p,%d): stub\n", lpPriorityList
, nCount
);
1440 /**************************************************************************
1441 * GetPriorityClipboardFormat (USER32.@)
1443 INT WINAPI
GetPriorityClipboardFormat( UINT
*lpPriorityList
, INT nCount
)
1448 if(CountClipboardFormats() == 0)
1453 for(Counter
= 0; Counter
<= nCount
; Counter
++)
1455 if(IsClipboardFormatAvailable(*(lpPriorityList
+sizeof(INT
)*Counter
)))
1456 return *(lpPriorityList
+sizeof(INT
)*Counter
);
1463 /**************************************************************************
1464 * GetClipboardSequenceNumber (USER32.@)
1465 * Supported on Win2k/Win98
1466 * MSDN: Windows clipboard code keeps a serial number for the clipboard
1467 * for each window station. The number is incremented whenever the
1468 * contents change or are emptied.
1469 * If you do not have WINSTA_ACCESSCLIPBOARD then the function returns 0
1471 DWORD WINAPI
GetClipboardSequenceNumber(VOID
)
1473 FIXME("Returning 0, see windows/clipboard.c\n");
1474 /* FIXME: Use serial numbers */