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"
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 dependent 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.
135 MESSAGEQUEUE *queue = QUEUE_Lock( GetFastQueue16() );
139 && queue->smWaiting->msg == WM_RENDERFORMAT
140 && queue->smWaiting->hSrcQueue
144 QUEUE_Unlock( queue );
146 /* FIXME: queue check no longer possible */
154 /**************************************************************************
155 * CLIPBOARD_ReleaseOwner
156 * Gives up ownership of the clipboard
158 void CLIPBOARD_ReleaseOwner()
164 /**************************************************************************
165 * CLIPBOARD_GlobalFreeProc
167 * This is a callback mechanism to allow HGLOBAL data to be released in
168 * the context of the process which allocated it. We post a WM_TIMER message
169 * to the owner window(in CLIPBOARD_DeleteRecord) and destroy the data(in idEvent)
170 * in this WndProc, which is invoked when the apps message loop calls DispatchMessage.
171 * This technique is discussed in Matt Pietrek's "Under the Hood".
172 * An article describing the same may be found in MSDN by searching for WM_TIMER.
173 * Note that this mechanism will probably stop working when WINE supports
174 * address space separation. When "queue events" are implemented in Wine we
175 * should switch to using that mechanism, since it is more robust and does not
176 * require a procedure address to be passed. See the SetWinEventHook API for
179 VOID CALLBACK CLIPBOARD_GlobalFreeProc( HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime )
181 /* idEvent is the HGLOBAL to be deleted */
182 GlobalFree( (HGLOBAL)idEvent );
185 /**************************************************************************
186 * CLIPBOARD_DeleteRecord
188 void CLIPBOARD_DeleteRecord(LPWINE_CLIPFORMAT lpFormat, BOOL bChange)
190 if( (lpFormat->wFormatID >= CF_GDIOBJFIRST &&
191 lpFormat->wFormatID <= CF_GDIOBJLAST) || lpFormat->wFormatID == CF_BITMAP
192 || lpFormat->wFormatID == CF_PALETTE)
194 if (lpFormat->hData32)
195 DeleteObject(lpFormat->hData32);
196 if (lpFormat->hData16)
197 DeleteObject(lpFormat->hData16);
199 else if( lpFormat->wFormatID == CF_METAFILEPICT )
201 if (lpFormat->hData32)
203 DeleteMetaFile( ((METAFILEPICT *)GlobalLock( lpFormat->hData32 ))->hMF );
204 PostMessageA(hWndClipOwner, WM_TIMER,
205 (WPARAM)lpFormat->hData32, (LPARAM)CLIPBOARD_GlobalFreeProc);
206 if (lpFormat->hDataSrc32)
208 /* Release lpFormat->hData32 in the context of the process which created it.
209 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
210 * GlobalFree(lpFormat->hDataSrc32);
212 PostMessageA(hWndClipOwner, WM_TIMER,
213 (WPARAM)lpFormat->hDataSrc32, (LPARAM)CLIPBOARD_GlobalFreeProc);
216 if (lpFormat->hData16)
217 /* HMETAFILE16 and HMETAFILE32 are apparently the same thing,
218 and a shallow copy is enough to share a METAFILEPICT
219 structure between 16bit and 32bit clipboards. The MetaFile
220 should of course only be deleted once. */
221 GlobalFree16(lpFormat->hData16);
223 if (lpFormat->hData16)
225 DeleteMetaFile16( ((METAFILEPICT16 *)GlobalLock16( lpFormat->hData16 ))->hMF );
226 GlobalFree16(lpFormat->hData16);
231 if (lpFormat->hData32)
233 /* Release lpFormat->hData32 in the context of the process which created it.
234 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
235 * GlobalFree( lpFormat->hData32 );
237 PostMessageA(hWndClipOwner, WM_TIMER,
238 (WPARAM)lpFormat->hData32, (LPARAM)CLIPBOARD_GlobalFreeProc);
240 if (lpFormat->hDataSrc32)
242 /* Release lpFormat->hData32 in the context of the process which created it.
243 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
244 * GlobalFree(lpFormat->hDataSrc32);
246 PostMessageA(hWndClipOwner, WM_TIMER,
247 (WPARAM)lpFormat->hDataSrc32, (LPARAM)CLIPBOARD_GlobalFreeProc);
249 if (lpFormat->hData16)
250 GlobalFree16(lpFormat->hData16);
253 lpFormat->wDataPresent = 0;
254 lpFormat->hData16 = 0;
255 lpFormat->hData32 = 0;
256 lpFormat->hDataSrc32 = 0;
257 lpFormat->drvData = 0;
259 if( bChange ) bCBHasChanged = TRUE;
262 /**************************************************************************
263 * CLIPBOARD_EmptyCache
265 void CLIPBOARD_EmptyCache( BOOL bChange )
267 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
271 if ( lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32 )
272 CLIPBOARD_DeleteRecord( lpFormat, bChange );
274 lpFormat = lpFormat->NextFormat;
278 /**************************************************************************
279 * CLIPBOARD_IsPresent
281 BOOL CLIPBOARD_IsPresent(WORD wFormat)
285 if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT || wFormat == CF_UNICODETEXT )
286 return ClipFormats[CF_TEXT-1].wDataPresent ||
287 ClipFormats[CF_OEMTEXT-1].wDataPresent ||
288 ClipFormats[CF_UNICODETEXT-1].wDataPresent;
291 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
292 if( lpFormat ) return (lpFormat->wDataPresent);
297 /**************************************************************************
298 * CLIPBOARD_IsCacheRendered
299 * Checks if any data needs to be rendered to the clipboard cache
301 * TRUE - All clipboard data is available in the cache
302 * FALSE - Some data is marked for delayed render and needs rendering
304 BOOL CLIPBOARD_IsCacheRendered()
306 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
308 /* check if all formats were rendered */
311 if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
314 lpFormat = lpFormat->NextFormat;
321 /**************************************************************************
322 * CLIPBOARD_IsMemoryObject
323 * Tests if the clipboard format specifies a memory object
325 BOOL CLIPBOARD_IsMemoryObject( WORD wFormat )
330 case CF_METAFILEPICT:
342 /***********************************************************************
343 * CLIPBOARD_GlobalDupMem( HGLOBAL )
344 * Helper method to duplicate an HGLOBAL chunk of memory into shared memory
346 HGLOBAL CLIPBOARD_GlobalDupMem( HGLOBAL hGlobalSrc )
349 PVOID pGlobalSrc, pGlobalDest;
355 cBytes = GlobalSize(hGlobalSrc);
359 /* Turn on the DDESHARE and _MOVEABLE flags explicitly */
360 hGlobalDest = GlobalAlloc( GlobalFlags(hGlobalSrc) | GMEM_DDESHARE | GMEM_MOVEABLE,
365 pGlobalSrc = GlobalLock(hGlobalSrc);
366 pGlobalDest = GlobalLock(hGlobalDest);
367 if ( !pGlobalSrc || !pGlobalDest )
370 memcpy(pGlobalDest, pGlobalSrc, cBytes);
372 GlobalUnlock(hGlobalSrc);
373 GlobalUnlock(hGlobalDest);
378 /**************************************************************************
379 * CLIPBOARD_GetFormatName
380 * Gets the format name associated with an ID
382 char * CLIPBOARD_GetFormatName(UINT wFormat)
384 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
385 return (lpFormat) ? lpFormat->Name : NULL;
389 /**************************************************************************
390 * CLIPBOARD_RenderFormat
392 static BOOL CLIPBOARD_RenderFormat(LPWINE_CLIPFORMAT lpFormat)
395 * If WINE is not the selection owner, and the format is available
396 * we must ask the driver to render the data to the clipboard cache.
398 TRACE("enter format=%d\n", lpFormat->wFormatID);
399 if ( !USER_Driver.pIsSelectionOwner()
400 && USER_Driver.pIsClipboardFormatAvailable( lpFormat->wFormatID ) )
402 if ( !USER_Driver.pGetClipboardData( lpFormat->wFormatID ) )
406 * If Wine owns the clipboard, and the data is marked for delayed render,
409 else if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
411 if( IsWindow(hWndClipOwner) )
413 /* Send a WM_RENDERFORMAT message to notify the owner to render the
414 * data requested into the clipboard.
416 TRACE("Sending WM_RENDERFORMAT message\n");
417 SendMessage16(hWndClipOwner,WM_RENDERFORMAT,
418 (WPARAM16)lpFormat->wFormatID,0L);
422 WARN("\thWndClipOwner (%04x) is lost!\n",
424 CLIPBOARD_ReleaseOwner();
425 lpFormat->wDataPresent = 0;
430 return (lpFormat->hData16 || lpFormat->hData32) ? TRUE : FALSE;
433 /**************************************************************************
434 * CLIPBOARD_ConvertText
435 * Returns number of required/converted characters - not bytes!
437 static INT CLIPBOARD_ConvertText(WORD src_fmt, void const *src, INT src_size,
438 WORD dst_fmt, void *dst, INT dst_size)
442 if(src_fmt == CF_UNICODETEXT)
455 return WideCharToMultiByte(cp, 0, src, src_size, dst, dst_size, NULL, NULL);
458 if(dst_fmt == CF_UNICODETEXT)
471 return MultiByteToWideChar(cp, 0, src, src_size, dst, dst_size);
474 if(!dst_size) return src_size;
476 if(dst_size > src_size) dst_size = src_size;
478 if(src_fmt == CF_TEXT )
479 CharToOemBuffA(src, dst, dst_size);
481 OemToCharBuffA(src, dst, dst_size);
486 /**************************************************************************
487 * CLIPBOARD_RenderText
489 * Renders text to the clipboard buffer converting between UNIX and DOS formats.
491 * RETURNS: pointer to the WINE_CLIPFORMAT if successful, NULL otherwise
493 * FIXME: Should be a pair of driver functions that convert between OEM text and Windows.
496 static LPWINE_CLIPFORMAT CLIPBOARD_RenderText( UINT wFormat )
498 LPWINE_CLIPFORMAT lpSource = ClipFormats;
499 LPWINE_CLIPFORMAT lpTarget = NULL;
500 BOOL foundData = FALSE;
502 /* Asked for CF_TEXT */
503 if( wFormat == CF_TEXT)
505 if(ClipFormats[CF_TEXT-1].wDataPresent)
507 lpSource = &ClipFormats[CF_TEXT-1];
508 lpTarget = &ClipFormats[CF_TEXT-1];
510 TRACE("\t TEXT -> TEXT\n");
512 else if(ClipFormats[CF_UNICODETEXT-1].wDataPresent)
514 /* Convert UNICODETEXT -> TEXT */
515 lpSource = &ClipFormats[CF_UNICODETEXT-1];
516 lpTarget = &ClipFormats[CF_TEXT-1];
518 TRACE("\tUNICODETEXT -> TEXT\n");
520 else if(ClipFormats[CF_OEMTEXT-1].wDataPresent)
522 /* Convert OEMTEXT -> TEXT */
523 lpSource = &ClipFormats[CF_OEMTEXT-1];
524 lpTarget = &ClipFormats[CF_TEXT-1];
526 TRACE("\tOEMTEXT -> TEXT\n");
529 /* Asked for CF_OEMTEXT */
530 else if( wFormat == CF_OEMTEXT)
532 if(ClipFormats[CF_OEMTEXT-1].wDataPresent)
534 lpSource = &ClipFormats[CF_OEMTEXT-1];
535 lpTarget = &ClipFormats[CF_OEMTEXT-1];
537 TRACE("\tOEMTEXT -> OEMTEXT\n");
539 else if(ClipFormats[CF_UNICODETEXT-1].wDataPresent)
541 /* Convert UNICODETEXT -> OEMTEXT */
542 lpSource = &ClipFormats[CF_UNICODETEXT-1];
543 lpTarget = &ClipFormats[CF_OEMTEXT-1];
545 TRACE("\tUNICODETEXT -> OEMTEXT\n");
547 else if(ClipFormats[CF_TEXT-1].wDataPresent)
549 /* Convert TEXT -> OEMTEXT */
550 lpSource = &ClipFormats[CF_TEXT-1];
551 lpTarget = &ClipFormats[CF_OEMTEXT-1];
553 TRACE("\tTEXT -> OEMTEXT\n");
556 /* Asked for CF_UNICODETEXT */
557 else if( wFormat == CF_UNICODETEXT )
559 if(ClipFormats[CF_UNICODETEXT-1].wDataPresent)
561 lpSource = &ClipFormats[CF_UNICODETEXT-1];
562 lpTarget = &ClipFormats[CF_UNICODETEXT-1];
564 TRACE("\tUNICODETEXT -> UNICODETEXT\n");
566 else if(ClipFormats[CF_TEXT-1].wDataPresent)
568 /* Convert TEXT -> UNICODETEXT */
569 lpSource = &ClipFormats[CF_TEXT-1];
570 lpTarget = &ClipFormats[CF_UNICODETEXT-1];
572 TRACE("\tTEXT -> UNICODETEXT\n");
574 else if(ClipFormats[CF_OEMTEXT-1].wDataPresent)
576 /* Convert OEMTEXT -> UNICODETEXT */
577 lpSource = &ClipFormats[CF_OEMTEXT-1];
578 lpTarget = &ClipFormats[CF_UNICODETEXT-1];
580 TRACE("\tOEMTEXT -> UNICODETEXT\n");
585 if ((wFormat == CF_TEXT) || (wFormat == CF_OEMTEXT))
587 lpSource = &ClipFormats[CF_UNICODETEXT-1];
588 lpTarget = __lookup_format( ClipFormats, wFormat );
592 lpSource = __lookup_format( ClipFormats, wFormat );
597 /* First render the source text format */
598 if ( !lpSource || !CLIPBOARD_RenderFormat(lpSource) ) return NULL;
600 /* Convert to the desired target text format, if necessary */
601 if( lpTarget != lpSource && !lpTarget->hData16 && !lpTarget->hData32 )
603 INT src_chars, dst_chars, alloc_size;
607 if (lpSource->hData32)
609 lpstrS = (LPSTR)GlobalLock(lpSource->hData32);
613 lpstrS = (LPSTR)GlobalLock16(lpSource->hData16);
616 if( !lpstrS ) return NULL;
618 /* Text always NULL terminated */
619 if(lpSource->wFormatID == CF_UNICODETEXT)
620 src_chars = strlenW((LPCWSTR)lpstrS)+1;
622 src_chars = strlen(lpstrS)+1;
624 /* Calculate number of characters in the destination buffer */
625 dst_chars = CLIPBOARD_ConvertText(lpSource->wFormatID, lpstrS, src_chars,
626 lpTarget->wFormatID, NULL, 0);
627 if(!dst_chars) return NULL;
629 TRACE("\tconverting from '%s' to '%s', %i chars\n",
630 lpSource->Name, lpTarget->Name, src_chars);
632 /* Convert characters to bytes */
633 if(lpTarget->wFormatID == CF_UNICODETEXT)
634 alloc_size = dst_chars * sizeof(WCHAR);
636 alloc_size = dst_chars;
638 lpTarget->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, alloc_size);
639 lpstrT = (LPSTR)GlobalLock(lpTarget->hData32);
643 CLIPBOARD_ConvertText(lpSource->wFormatID, lpstrS, src_chars,
644 lpTarget->wFormatID, lpstrT, dst_chars);
645 GlobalUnlock(lpTarget->hData32);
648 lpTarget->hData32 = 0;
651 if (lpSource->hData32)
652 GlobalUnlock(lpSource->hData32);
654 GlobalUnlock16(lpSource->hData16);
657 return (lpTarget->hData16 || lpTarget->hData32) ? lpTarget : NULL;
660 /**************************************************************************
661 * CLIPBOARD_EnumClipboardFormats (internal)
663 static UINT CLIPBOARD_EnumClipboardFormats( UINT wFormat )
665 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
668 if (wFormat == 0) /* start from the beginning */
669 lpFormat = ClipFormats;
672 /* walk up to the specified format record */
674 if( !(lpFormat = __lookup_format( lpFormat, wFormat )) )
676 lpFormat = lpFormat->NextFormat; /* right */
681 if (lpFormat == NULL) return 0;
683 if(CLIPBOARD_IsPresent(lpFormat->wFormatID))
686 /* Query the driver if not yet in the cache */
687 if (!USER_Driver.pIsSelectionOwner())
689 if(lpFormat->wFormatID == CF_UNICODETEXT ||
690 lpFormat->wFormatID == CF_TEXT ||
691 lpFormat->wFormatID == CF_OEMTEXT)
693 if(USER_Driver.pIsClipboardFormatAvailable(CF_UNICODETEXT) ||
694 USER_Driver.pIsClipboardFormatAvailable(CF_TEXT) ||
695 USER_Driver.pIsClipboardFormatAvailable(CF_OEMTEXT))
696 bFormatPresent = TRUE;
698 bFormatPresent = FALSE;
701 bFormatPresent = USER_Driver.pIsClipboardFormatAvailable(lpFormat->wFormatID);
707 lpFormat = lpFormat->NextFormat;
710 TRACE("Next available format %d\n", lpFormat->wFormatID);
712 return lpFormat->wFormatID;
716 /**************************************************************************
717 * WIN32 Clipboard implementation
718 **************************************************************************/
720 /**************************************************************************
721 * OpenClipboard (USER.137)
723 BOOL16 WINAPI OpenClipboard16( HWND16 hWnd )
725 return OpenClipboard( hWnd );
729 /**************************************************************************
730 * OpenClipboard (USER32.@)
732 * Note: Netscape uses NULL hWnd to open the clipboard.
734 BOOL WINAPI OpenClipboard( HWND hWnd )
738 TRACE("(%04x)...\n", hWnd);
742 hClipLock = GetCurrentTask();
744 /* Save current user of the clipboard */
745 hWndClipWindow = hWnd;
746 bCBHasChanged = FALSE;
751 TRACE(" returning %i\n", bRet);
756 /**************************************************************************
757 * CloseClipboard (USER.138)
759 BOOL16 WINAPI CloseClipboard16(void)
761 return CloseClipboard();
765 /**************************************************************************
766 * CloseClipboard (USER32.@)
768 BOOL WINAPI CloseClipboard(void)
772 if (hClipLock == GetCurrentTask())
776 if (bCBHasChanged && hWndViewer)
777 SendMessage16(hWndViewer, WM_DRAWCLIPBOARD, 0, 0L);
784 /**************************************************************************
785 * EmptyClipboard (USER.139)
787 BOOL16 WINAPI EmptyClipboard16(void)
789 return EmptyClipboard();
793 /**************************************************************************
794 * EmptyClipboard (USER32.@)
795 * Empties and acquires ownership of the clipboard
797 BOOL WINAPI EmptyClipboard(void)
801 if (hClipLock != GetCurrentTask())
803 WARN("Clipboard not opened by calling task!\n");
807 /* destroy private objects */
810 SendMessage16(hWndClipOwner, WM_DESTROYCLIPBOARD, 0, 0L);
812 /* empty the cache */
813 CLIPBOARD_EmptyCache(TRUE);
815 /* Assign ownership of the clipboard to the current client */
816 hWndClipOwner = hWndClipWindow;
818 /* Save the current task */
819 hTaskClipOwner = GetCurrentTask();
821 /* Tell the driver to acquire the selection */
822 USER_Driver.pAcquireClipboard();
828 /**************************************************************************
829 * GetClipboardOwner (USER.140)
830 * FIXME: Can't return the owner if the clipbard is owned by an external app
832 HWND16 WINAPI GetClipboardOwner16(void)
835 return hWndClipOwner;
839 /**************************************************************************
840 * GetClipboardOwner (USER32.@)
841 * FIXME: Can't return the owner if the clipbard is owned by an external app
843 HWND WINAPI GetClipboardOwner(void)
846 return hWndClipOwner;
850 /**************************************************************************
851 * SetClipboardData (USER.141)
853 HANDLE16 WINAPI SetClipboardData16( UINT16 wFormat, HANDLE16 hData )
855 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
857 TRACE("(%04X, %04x) !\n", wFormat, hData);
859 /* NOTE: If the hData is zero and current owner doesn't match
860 * the window that opened the clipboard then this application
861 * is screwed because WM_RENDERFORMAT will go to the owner.
862 * (to become the owner it must call EmptyClipboard() before
866 if( CLIPBOARD_IsLocked() || !lpFormat ||
867 (!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) )
869 WARN("Invalid hData or clipboard not opened by calling task!\n");
873 /* Pass on the request to the driver */
874 USER_Driver.pSetClipboardData(wFormat);
876 if ( lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32 )
878 CLIPBOARD_DeleteRecord(lpFormat, TRUE);
880 /* delete existing CF_UNICODETEXT/CF_TEXT/CF_OEMTEXT aliases */
881 if(wFormat == CF_UNICODETEXT)
883 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
884 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
886 else if(wFormat == CF_TEXT)
888 CLIPBOARD_DeleteRecord(&ClipFormats[CF_UNICODETEXT-1], TRUE);
889 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
891 else if(wFormat == CF_OEMTEXT)
893 CLIPBOARD_DeleteRecord(&ClipFormats[CF_UNICODETEXT-1], TRUE);
894 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
898 bCBHasChanged = TRUE;
899 lpFormat->wDataPresent = 1;
900 lpFormat->hData16 = hData; /* 0 is legal, see WM_RENDERFORMAT */
901 lpFormat->hData32 = 0;
903 return lpFormat->hData16;
907 /**************************************************************************
908 * SetClipboardData (USER32.@)
910 HANDLE WINAPI SetClipboardData( UINT wFormat, HANDLE hData )
912 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
914 TRACE("(%08X, %08x) !\n", wFormat, hData);
916 /* NOTE: If the hData is zero and current owner doesn't match
917 * the window that opened the clipboard then this application
918 * is screwed because WM_RENDERFORMAT will go to the owner.
919 * (to become the owner it must call EmptyClipboard() before
923 if( CLIPBOARD_IsLocked() || !lpFormat ||
924 (!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) )
926 WARN("Invalid hData or clipboard not opened by calling task!\n");
930 /* Tell the driver to acquire the selection */
931 USER_Driver.pAcquireClipboard();
933 if ( lpFormat->wDataPresent &&
934 (lpFormat->hData16 || lpFormat->hData32) )
936 CLIPBOARD_DeleteRecord(lpFormat, TRUE);
938 /* delete existing CF_UNICODETEXT/CF_TEXT/CF_OEMTEXT aliases */
939 if(wFormat == CF_UNICODETEXT)
941 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
942 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
944 else if(wFormat == CF_TEXT)
946 CLIPBOARD_DeleteRecord(&ClipFormats[CF_UNICODETEXT-1], TRUE);
947 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
949 else if(wFormat == CF_OEMTEXT)
951 CLIPBOARD_DeleteRecord(&ClipFormats[CF_UNICODETEXT-1], TRUE);
952 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
956 bCBHasChanged = TRUE;
957 lpFormat->wDataPresent = 1;
958 lpFormat->hDataSrc32 = hData; /* Save the source handle */
961 * Make a shared duplicate if the memory is not shared
962 * TODO: What should be done for non-memory objects
964 if ( CLIPBOARD_IsMemoryObject(wFormat) && hData && !(GlobalFlags(hData) & GMEM_DDESHARE) )
965 lpFormat->hData32 = CLIPBOARD_GlobalDupMem( hData );
967 lpFormat->hData32 = hData; /* 0 is legal, see WM_RENDERFORMAT */
969 lpFormat->hData16 = 0;
971 return lpFormat->hData32; /* Should we return lpFormat->hDataSrc32 */
975 /**************************************************************************
976 * GetClipboardData (USER.142)
978 HANDLE16 WINAPI GetClipboardData16( UINT16 wFormat )
980 LPWINE_CLIPFORMAT lpRender = ClipFormats;
982 TRACE("(%04X)\n", wFormat);
984 if (CLIPBOARD_IsLocked())
986 WARN("Clipboard not opened by calling task!\n");
990 if( wFormat == CF_UNICODETEXT || wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
992 lpRender = CLIPBOARD_RenderText(wFormat);
993 if ( !lpRender ) return 0;
997 lpRender = __lookup_format( ClipFormats, wFormat );
998 if( !lpRender || !CLIPBOARD_RenderFormat(lpRender) ) return 0;
1001 /* Convert between 32 -> 16 bit data, if necessary */
1002 if( lpRender->hData32 && !lpRender->hData16
1003 && CLIPBOARD_IsMemoryObject(wFormat) )
1006 if( lpRender->wFormatID == CF_METAFILEPICT )
1007 size = sizeof( METAFILEPICT16 );
1009 size = GlobalSize(lpRender->hData32);
1011 lpRender->hData16 = GlobalAlloc16(GMEM_ZEROINIT, size);
1012 if( !lpRender->hData16 )
1013 ERR("(%04X) -- not enough memory in 16b heap\n", wFormat);
1016 if( lpRender->wFormatID == CF_METAFILEPICT )
1018 FIXME("\timplement function CopyMetaFilePict32to16\n");
1019 FIXME("\tin the appropriate file.\n");
1020 #ifdef SOMEONE_IMPLEMENTED_ME
1021 CopyMetaFilePict32to16( GlobalLock16(lpRender->hData16),
1022 GlobalLock(lpRender->hData32) );
1027 memcpy( GlobalLock16(lpRender->hData16),
1028 GlobalLock(lpRender->hData32),
1031 GlobalUnlock16(lpRender->hData16);
1032 GlobalUnlock(lpRender->hData32);
1036 TRACE("\treturning %04x (type %i)\n",
1037 lpRender->hData16, lpRender->wFormatID);
1038 return lpRender->hData16;
1042 /**************************************************************************
1043 * GetClipboardData (USER32.@)
1045 HANDLE WINAPI GetClipboardData( UINT wFormat )
1047 LPWINE_CLIPFORMAT lpRender = ClipFormats;
1049 TRACE("(%08X)\n", wFormat);
1051 if (CLIPBOARD_IsLocked())
1053 WARN("Clipboard not opened by calling task!\n");
1057 if( wFormat == CF_UNICODETEXT || wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
1059 lpRender = CLIPBOARD_RenderText(wFormat);
1060 if ( !lpRender ) return 0;
1064 lpRender = __lookup_format( ClipFormats, wFormat );
1065 if( !lpRender || !CLIPBOARD_RenderFormat(lpRender) ) return 0;
1068 /* Convert between 16 -> 32 bit data, if necessary */
1069 if( lpRender->hData16 && !lpRender->hData32
1070 && CLIPBOARD_IsMemoryObject(wFormat) )
1073 if( lpRender->wFormatID == CF_METAFILEPICT )
1074 size = sizeof( METAFILEPICT );
1076 size = GlobalSize16(lpRender->hData16);
1077 lpRender->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE,
1079 if( lpRender->wFormatID == CF_METAFILEPICT )
1081 FIXME("\timplement function CopyMetaFilePict16to32\n");
1082 FIXME("\tin the appropriate file.\n");
1083 #ifdef SOMEONE_IMPLEMENTED_ME
1084 CopyMetaFilePict16to32( GlobalLock16(lpRender->hData32),
1085 GlobalLock(lpRender->hData16) );
1090 memcpy( GlobalLock(lpRender->hData32),
1091 GlobalLock16(lpRender->hData16),
1094 GlobalUnlock(lpRender->hData32);
1095 GlobalUnlock16(lpRender->hData16);
1098 TRACE("\treturning %04x (type %i)\n",
1099 lpRender->hData32, lpRender->wFormatID);
1100 return lpRender->hData32;
1104 /**************************************************************************
1105 * CountClipboardFormats (USER.143)
1107 INT16 WINAPI CountClipboardFormats16(void)
1109 return CountClipboardFormats();
1113 /**************************************************************************
1114 * CountClipboardFormats (USER32.@)
1116 INT WINAPI CountClipboardFormats(void)
1118 INT FormatCount = 0;
1119 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
1125 if (lpFormat == NULL) break;
1127 if( lpFormat->wFormatID != CF_TEXT ) /* Don't count CF_TEXT */
1130 * The format is available if either:
1131 * 1. The data is already in the cache.
1132 * 2. The selection is not owned by us(WINE) and the data is
1133 * available to the clipboard driver.
1135 if ( lpFormat->wDataPresent ||
1136 ( !USER_Driver.pIsSelectionOwner()
1137 && USER_Driver.pIsClipboardFormatAvailable( lpFormat->wFormatID ) ) )
1139 TRACE("\tdata found for format 0x%04x(%s)\n",
1140 lpFormat->wFormatID, CLIPBOARD_GetFormatName(lpFormat->wFormatID));
1145 lpFormat = lpFormat->NextFormat;
1148 /* these are equivalent, adjust the total */
1149 FormatCount += (ClipFormats[CF_UNICODETEXT-1].wDataPresent ||
1150 ClipFormats[CF_TEXT-1].wDataPresent ||
1151 ClipFormats[CF_OEMTEXT-1].wDataPresent) ? 1 : 0;
1153 TRACE("\ttotal %d\n", FormatCount);
1157 /**************************************************************************
1158 * EnumClipboardFormats (USER.144)
1160 UINT16 WINAPI EnumClipboardFormats16( UINT16 wFormat )
1162 return EnumClipboardFormats( wFormat );
1166 /**************************************************************************
1167 * EnumClipboardFormats (USER32.@)
1169 UINT WINAPI EnumClipboardFormats( UINT wFormat )
1171 TRACE("(%04X)\n", wFormat);
1173 if (CLIPBOARD_IsLocked())
1175 WARN("Clipboard not opened by calling task!\n");
1179 return CLIPBOARD_EnumClipboardFormats(wFormat);
1183 /**************************************************************************
1184 * RegisterClipboardFormat (USER.145)
1186 UINT16 WINAPI RegisterClipboardFormat16( LPCSTR FormatName )
1188 LPWINE_CLIPFORMAT lpNewFormat;
1189 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
1191 if (FormatName == NULL) return 0;
1193 TRACE("('%s') !\n", FormatName);
1195 /* walk format chain to see if it's already registered */
1199 if ( !strcmp(lpFormat->Name,FormatName) )
1201 lpFormat->wRefCount++;
1202 return lpFormat->wFormatID;
1205 if ( lpFormat->NextFormat == NULL ) break;
1207 lpFormat = lpFormat->NextFormat;
1210 /* allocate storage for new format entry */
1212 lpNewFormat = (LPWINE_CLIPFORMAT)HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_CLIPFORMAT));
1213 if(lpNewFormat == NULL) {
1214 WARN("No more memory for a new format!\n");
1217 lpFormat->NextFormat = lpNewFormat;
1218 lpNewFormat->wFormatID = LastRegFormat;
1219 lpNewFormat->wRefCount = 1;
1221 lpNewFormat->Name = (LPSTR)HEAP_strdupA(GetProcessHeap(), 0, FormatName);
1222 if(lpNewFormat->Name == NULL) {
1223 WARN("No more memory for the new format name!\n");
1224 HeapFree(GetProcessHeap(), 0, lpNewFormat);
1228 lpNewFormat->wDataPresent = 0;
1229 lpNewFormat->hData16 = 0;
1230 lpNewFormat->hDataSrc32 = 0;
1231 lpNewFormat->hData32 = 0;
1232 lpNewFormat->drvData = 0;
1233 lpNewFormat->PrevFormat = lpFormat;
1234 lpNewFormat->NextFormat = NULL;
1236 /* Pass on the registration request to the driver */
1237 USER_Driver.pRegisterClipboardFormat( FormatName );
1239 return LastRegFormat++;
1243 /**************************************************************************
1244 * RegisterClipboardFormatA (USER32.@)
1246 UINT WINAPI RegisterClipboardFormatA( LPCSTR formatName )
1248 return RegisterClipboardFormat16( formatName );
1252 /**************************************************************************
1253 * RegisterClipboardFormatW (USER32.@)
1255 UINT WINAPI RegisterClipboardFormatW( LPCWSTR formatName )
1257 LPSTR aFormat = HEAP_strdupWtoA( GetProcessHeap(), 0, formatName );
1258 UINT ret = RegisterClipboardFormatA( aFormat );
1259 HeapFree( GetProcessHeap(), 0, aFormat );
1264 /**************************************************************************
1265 * GetClipboardFormatName (USER.146)
1267 INT16 WINAPI GetClipboardFormatName16( UINT16 wFormat, LPSTR retStr, INT16 maxlen )
1269 return GetClipboardFormatNameA( wFormat, retStr, maxlen );
1273 /**************************************************************************
1274 * GetClipboardFormatNameA (USER32.@)
1276 INT WINAPI GetClipboardFormatNameA( UINT wFormat, LPSTR retStr, INT maxlen )
1278 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
1280 TRACE("(%04X, %p, %d) !\n", wFormat, retStr, maxlen);
1282 if (lpFormat == NULL || lpFormat->Name == NULL ||
1283 lpFormat->wFormatID < CF_REGFORMATBASE) return 0;
1285 TRACE("Name='%s' !\n", lpFormat->Name);
1287 lstrcpynA( retStr, lpFormat->Name, maxlen );
1288 return strlen(retStr);
1292 /**************************************************************************
1293 * GetClipboardFormatNameW (USER32.@)
1295 INT WINAPI GetClipboardFormatNameW( UINT wFormat, LPWSTR retStr, INT maxlen )
1298 LPSTR p = HeapAlloc( GetProcessHeap(), 0, maxlen );
1299 if(p == NULL) return 0; /* FIXME: is this the correct failure value? */
1301 ret = GetClipboardFormatNameA( wFormat, p, maxlen );
1303 if (maxlen > 0 && !MultiByteToWideChar( CP_ACP, 0, p, -1, retStr, maxlen ))
1304 retStr[maxlen-1] = 0;
1305 HeapFree( GetProcessHeap(), 0, p );
1310 /**************************************************************************
1311 * SetClipboardViewer (USER.147)
1313 HWND16 WINAPI SetClipboardViewer16( HWND16 hWnd )
1315 TRACE("(%04x)\n", hWnd);
1316 return SetClipboardViewer( hWnd );
1320 /**************************************************************************
1321 * SetClipboardViewer (USER32.@)
1323 HWND WINAPI SetClipboardViewer( HWND hWnd )
1325 HWND hwndPrev = hWndViewer;
1327 TRACE("(%04x): returning %04x\n", hWnd, hwndPrev);
1334 /**************************************************************************
1335 * GetClipboardViewer (USER.148)
1337 HWND16 WINAPI GetClipboardViewer16(void)
1344 /**************************************************************************
1345 * GetClipboardViewer (USER32.@)
1347 HWND WINAPI GetClipboardViewer(void)
1354 /**************************************************************************
1355 * ChangeClipboardChain (USER.149)
1357 BOOL16 WINAPI ChangeClipboardChain16(HWND16 hWnd, HWND16 hWndNext)
1359 return ChangeClipboardChain(hWnd, hWndNext);
1363 /**************************************************************************
1364 * ChangeClipboardChain (USER32.@)
1366 BOOL WINAPI ChangeClipboardChain(HWND hWnd, HWND hWndNext)
1370 FIXME("(0x%04x, 0x%04x): stub?\n", hWnd, hWndNext);
1373 bRet = !SendMessage16( hWndViewer, WM_CHANGECBCHAIN,
1374 (WPARAM16)hWnd, (LPARAM)hWndNext);
1376 WARN("hWndViewer is lost\n");
1378 if( hWnd == hWndViewer ) hWndViewer = hWndNext;
1384 /**************************************************************************
1385 * IsClipboardFormatAvailable (USER.193)
1387 BOOL16 WINAPI IsClipboardFormatAvailable16( UINT16 wFormat )
1389 return IsClipboardFormatAvailable( wFormat );
1393 /**************************************************************************
1394 * IsClipboardFormatAvailable (USER32.@)
1396 BOOL WINAPI IsClipboardFormatAvailable( UINT wFormat )
1400 if (wFormat == 0) /* Reject this case quickly */
1404 UINT iret = CLIPBOARD_EnumClipboardFormats(wFormat - 1);
1405 if ((wFormat == CF_TEXT) || (wFormat == CF_OEMTEXT) || (wFormat == CF_UNICODETEXT))
1406 bRet = ((iret == CF_TEXT) || (iret == CF_OEMTEXT) || (iret == CF_UNICODETEXT));
1408 bRet = iret == wFormat;
1410 TRACE("(%04X)- ret(%d)\n", wFormat, bRet);
1415 /**************************************************************************
1416 * GetOpenClipboardWindow (USER.248)
1417 * FIXME: This wont work if an external app owns the selection
1419 HWND16 WINAPI GetOpenClipboardWindow16(void)
1422 return hWndClipWindow;
1426 /**************************************************************************
1427 * GetOpenClipboardWindow (USER32.@)
1428 * FIXME: This wont work if an external app owns the selection
1430 HWND WINAPI GetOpenClipboardWindow(void)
1433 return hWndClipWindow;
1437 /**************************************************************************
1438 * GetPriorityClipboardFormat (USER.402)
1440 INT16 WINAPI GetPriorityClipboardFormat16( UINT16 *lpPriorityList, INT16 nCount)
1442 FIXME("(%p,%d): stub\n", lpPriorityList, nCount );
1447 /**************************************************************************
1448 * GetPriorityClipboardFormat (USER32.@)
1450 INT WINAPI GetPriorityClipboardFormat( UINT *lpPriorityList, INT nCount )
1455 if(CountClipboardFormats() == 0)
1460 for(Counter = 0; Counter <= nCount; Counter++)
1462 if(IsClipboardFormatAvailable(*(lpPriorityList+sizeof(INT)*Counter)))
1463 return *(lpPriorityList+sizeof(INT)*Counter);
1470 /**************************************************************************
1471 * GetClipboardSequenceNumber (USER32.@)
1472 * Supported on Win2k/Win98
1473 * MSDN: Windows clipboard code keeps a serial number for the clipboard
1474 * for each window station. The number is incremented whenever the
1475 * contents change or are emptied.
1476 * If you do not have WINSTA_ACCESSCLIPBOARD then the function returns 0
1478 DWORD WINAPI GetClipboardSequenceNumber(VOID)
1480 FIXME("Returning 0, see windows/clipboard.c\n");
1481 /* FIXME: Use serial numbers */