2 * WIN32 clipboard implementation
4 * Copyright 1994 Martin Ayotte
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * This file contains the implementation for the WIN32 Clipboard API
24 * and Wine's internal clipboard cache.
25 * The actual contents of the clipboard are held in the clipboard cache.
26 * The internal implementation talks to a "clipboard driver" to fill or
27 * expose the cache to the native device. (Currently only the X11 and
28 * TTY clipboard driver are available)
32 #include <sys/types.h>
41 #include "wine/winuser16.h"
42 #include "wine/winbase16.h"
46 #include "clipboard.h"
47 #include "wine/debug.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(clipboard);
51 #define CF_REGFORMATBASE 0xC000
53 /**************************************************************************
54 * Clipboard context global variables
57 static HANDLE hClipLock = 0;
58 static BOOL bCBHasChanged = FALSE;
60 static HWND hWndClipWindow; /* window that last opened clipboard */
61 static HWND hWndClipOwner; /* current clipboard owner */
62 static HANDLE16 hTaskClipOwner; /* clipboard owner's task */
63 static HWND hWndViewer; /* start of viewers chain */
65 static WORD LastRegFormat = CF_REGFORMATBASE;
67 /* Clipboard cache initial data.
68 * WARNING: This data ordering is dependent on the WINE_CLIPFORMAT structure
69 * declared in clipboard.h
71 WINE_CLIPFORMAT ClipFormats[] = {
72 { CF_TEXT, 1, 0, "Text", 0, 0, 0, 0, NULL, &ClipFormats[1]},
73 { CF_BITMAP, 1, 0, "Bitmap", 0, 0, 0, 0, &ClipFormats[0], &ClipFormats[2]},
74 { CF_METAFILEPICT, 1, 0, "MetaFile Picture", 0, 0, 0, 0, &ClipFormats[1], &ClipFormats[3]},
75 { CF_SYLK, 1, 0, "Sylk", 0, 0, 0, 0, &ClipFormats[2], &ClipFormats[4]},
76 { CF_DIF, 1, 0, "DIF", 0, 0, 0, 0, &ClipFormats[3], &ClipFormats[5]},
77 { CF_TIFF, 1, 0, "TIFF", 0, 0, 0, 0, &ClipFormats[4], &ClipFormats[6]},
78 { CF_OEMTEXT, 1, 0, "OEM Text", 0, 0, 0, 0, &ClipFormats[5], &ClipFormats[7]},
79 { CF_DIB, 1, 0, "DIB", 0, 0, 0, 0, &ClipFormats[6], &ClipFormats[8]},
80 { CF_PALETTE, 1, 0, "Palette", 0, 0, 0, 0, &ClipFormats[7], &ClipFormats[9]},
81 { CF_PENDATA, 1, 0, "PenData", 0, 0, 0, 0, &ClipFormats[8], &ClipFormats[10]},
82 { CF_RIFF, 1, 0, "RIFF", 0, 0, 0, 0, &ClipFormats[9], &ClipFormats[11]},
83 { CF_WAVE, 1, 0, "Wave", 0, 0, 0, 0, &ClipFormats[10], &ClipFormats[12]},
84 { CF_UNICODETEXT, 1, 0, "Unicode Text", 0, 0, 0, 0, &ClipFormats[11], &ClipFormats[13]},
85 { CF_OWNERDISPLAY, 1, 0, "Owner Display", 0, 0, 0, 0, &ClipFormats[12], &ClipFormats[14]},
86 { CF_DSPTEXT, 1, 0, "DSPText", 0, 0, 0, 0, &ClipFormats[13], &ClipFormats[15]},
87 { CF_DSPMETAFILEPICT, 1, 0, "DSPMetaFile Picture", 0, 0, 0, 0, &ClipFormats[14], &ClipFormats[16]},
88 { CF_DSPBITMAP, 1, 0, "DSPBitmap", 0, 0, 0, 0, &ClipFormats[15], &ClipFormats[17]},
89 { CF_HDROP, 1, 0, "HDROP", 0, 0, 0, 0, &ClipFormats[16], NULL}
93 /**************************************************************************
94 * Internal Clipboard implementation methods
95 **************************************************************************/
98 /**************************************************************************
99 * CLIPBOARD_LookupFormat
101 static LPWINE_CLIPFORMAT __lookup_format( LPWINE_CLIPFORMAT lpFormat, WORD wID )
105 if (lpFormat == NULL ||
106 lpFormat->wFormatID == wID) break;
107 lpFormat = lpFormat->NextFormat;
112 LPWINE_CLIPFORMAT CLIPBOARD_LookupFormat( WORD wID )
114 return __lookup_format( ClipFormats, wID );
117 /**************************************************************************
119 * Check if the clipboard cache is available to the caller
121 BOOL CLIPBOARD_IsLocked()
123 BOOL bIsLocked = TRUE;
124 HANDLE16 hTaskCur = GetCurrentTask();
127 * The clipboard is available:
128 * 1. if the caller's task has opened the clipboard,
130 * 2. if the caller is the clipboard owners task, AND is responding to a
131 * WM_RENDERFORMAT message.
133 if ( hClipLock == hTaskCur )
136 else if ( hTaskCur == hTaskClipOwner )
138 /* Check if we're currently executing inside a window procedure
139 * called in response to a WM_RENDERFORMAT message. A WM_RENDERFORMAT
140 * handler is not permitted to open the clipboard since it has been opened
141 * by another client. However the handler must have access to the
142 * clipboard in order to update data in response to this message.
145 MESSAGEQUEUE *queue = QUEUE_Current();
149 && queue->smWaiting->msg == WM_RENDERFORMAT
150 && queue->smWaiting->hSrcQueue
154 /* FIXME: queue check no longer possible */
162 /**************************************************************************
163 * CLIPBOARD_ReleaseOwner
164 * Gives up ownership of the clipboard
166 void CLIPBOARD_ReleaseOwner()
172 /**************************************************************************
173 * CLIPBOARD_GlobalFreeProc
175 * This is a callback mechanism to allow HGLOBAL data to be released in
176 * the context of the process which allocated it. We post a WM_TIMER message
177 * to the owner window(in CLIPBOARD_DeleteRecord) and destroy the data(in idEvent)
178 * in this WndProc, which is invoked when the apps message loop calls DispatchMessage.
179 * This technique is discussed in Matt Pietrek's "Under the Hood".
180 * An article describing the same may be found in MSDN by searching for WM_TIMER.
181 * Note that this mechanism will probably stop working when WINE supports
182 * address space separation. When "queue events" are implemented in Wine we
183 * should switch to using that mechanism, since it is more robust and does not
184 * require a procedure address to be passed. See the SetWinEventHook API for
187 VOID CALLBACK CLIPBOARD_GlobalFreeProc( HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime )
189 /* idEvent is the HGLOBAL to be deleted */
190 GlobalFree( (HGLOBAL)idEvent );
193 /**************************************************************************
194 * CLIPBOARD_DeleteRecord
196 void CLIPBOARD_DeleteRecord(LPWINE_CLIPFORMAT lpFormat, BOOL bChange)
198 if( (lpFormat->wFormatID >= CF_GDIOBJFIRST &&
199 lpFormat->wFormatID <= CF_GDIOBJLAST) || lpFormat->wFormatID == CF_BITMAP
200 || lpFormat->wFormatID == CF_PALETTE)
202 if (lpFormat->hData32)
203 DeleteObject(lpFormat->hData32);
204 if (lpFormat->hData16)
205 DeleteObject(lpFormat->hData16);
207 else if( lpFormat->wFormatID == CF_METAFILEPICT )
209 if (lpFormat->hData32)
211 DeleteMetaFile( ((METAFILEPICT *)GlobalLock( lpFormat->hData32 ))->hMF );
212 PostMessageA(hWndClipOwner, WM_TIMER,
213 (WPARAM)lpFormat->hData32, (LPARAM)CLIPBOARD_GlobalFreeProc);
214 if (lpFormat->hDataSrc32)
216 /* Release lpFormat->hData32 in the context of the process which created it.
217 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
218 * GlobalFree(lpFormat->hDataSrc32);
220 PostMessageA(hWndClipOwner, WM_TIMER,
221 (WPARAM)lpFormat->hDataSrc32, (LPARAM)CLIPBOARD_GlobalFreeProc);
224 if (lpFormat->hData16)
225 /* HMETAFILE16 and HMETAFILE32 are apparently the same thing,
226 and a shallow copy is enough to share a METAFILEPICT
227 structure between 16bit and 32bit clipboards. The MetaFile
228 should of course only be deleted once. */
229 GlobalFree16(lpFormat->hData16);
231 if (lpFormat->hData16)
233 DeleteMetaFile16( ((METAFILEPICT16 *)GlobalLock16( lpFormat->hData16 ))->hMF );
234 GlobalFree16(lpFormat->hData16);
239 if (lpFormat->hData32)
241 /* Release lpFormat->hData32 in the context of the process which created it.
242 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
243 * GlobalFree( lpFormat->hData32 );
245 PostMessageA(hWndClipOwner, WM_TIMER,
246 (WPARAM)lpFormat->hData32, (LPARAM)CLIPBOARD_GlobalFreeProc);
248 if (lpFormat->hDataSrc32)
250 /* Release lpFormat->hData32 in the context of the process which created it.
251 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
252 * GlobalFree(lpFormat->hDataSrc32);
254 PostMessageA(hWndClipOwner, WM_TIMER,
255 (WPARAM)lpFormat->hDataSrc32, (LPARAM)CLIPBOARD_GlobalFreeProc);
257 if (lpFormat->hData16)
258 GlobalFree16(lpFormat->hData16);
261 lpFormat->wDataPresent = 0;
262 lpFormat->hData16 = 0;
263 lpFormat->hData32 = 0;
264 lpFormat->hDataSrc32 = 0;
265 lpFormat->drvData = 0;
267 if( bChange ) bCBHasChanged = TRUE;
270 /**************************************************************************
271 * CLIPBOARD_EmptyCache
273 void CLIPBOARD_EmptyCache( BOOL bChange )
275 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
279 if ( lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32 )
280 CLIPBOARD_DeleteRecord( lpFormat, bChange );
282 lpFormat = lpFormat->NextFormat;
286 /**************************************************************************
287 * CLIPBOARD_IsPresent
289 BOOL CLIPBOARD_IsPresent(WORD wFormat)
293 if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT || wFormat == CF_UNICODETEXT )
294 return ClipFormats[CF_TEXT-1].wDataPresent ||
295 ClipFormats[CF_OEMTEXT-1].wDataPresent ||
296 ClipFormats[CF_UNICODETEXT-1].wDataPresent;
299 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
300 if( lpFormat ) return (lpFormat->wDataPresent);
305 /**************************************************************************
306 * CLIPBOARD_IsCacheRendered
307 * Checks if any data needs to be rendered to the clipboard cache
309 * TRUE - All clipboard data is available in the cache
310 * FALSE - Some data is marked for delayed render and needs rendering
312 BOOL CLIPBOARD_IsCacheRendered()
314 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
316 /* check if all formats were rendered */
319 if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
322 lpFormat = lpFormat->NextFormat;
329 /**************************************************************************
330 * CLIPBOARD_IsMemoryObject
331 * Tests if the clipboard format specifies a memory object
333 BOOL CLIPBOARD_IsMemoryObject( WORD wFormat )
338 case CF_METAFILEPICT:
350 /***********************************************************************
351 * CLIPBOARD_GlobalDupMem( HGLOBAL )
352 * Helper method to duplicate an HGLOBAL chunk of memory into shared memory
354 HGLOBAL CLIPBOARD_GlobalDupMem( HGLOBAL hGlobalSrc )
357 PVOID pGlobalSrc, pGlobalDest;
363 cBytes = GlobalSize(hGlobalSrc);
367 /* Turn on the DDESHARE and _MOVEABLE flags explicitly */
368 hGlobalDest = GlobalAlloc( GlobalFlags(hGlobalSrc) | GMEM_DDESHARE | GMEM_MOVEABLE,
373 pGlobalSrc = GlobalLock(hGlobalSrc);
374 pGlobalDest = GlobalLock(hGlobalDest);
375 if ( !pGlobalSrc || !pGlobalDest )
378 memcpy(pGlobalDest, pGlobalSrc, cBytes);
380 GlobalUnlock(hGlobalSrc);
381 GlobalUnlock(hGlobalDest);
386 /**************************************************************************
387 * CLIPBOARD_GetFormatName
388 * Gets the format name associated with an ID
390 char * CLIPBOARD_GetFormatName(UINT wFormat)
392 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
393 return (lpFormat) ? lpFormat->Name : NULL;
397 /**************************************************************************
398 * CLIPBOARD_RenderFormat
400 static BOOL CLIPBOARD_RenderFormat(LPWINE_CLIPFORMAT lpFormat)
403 * If WINE is not the selection owner, and the format is available
404 * we must ask the driver to render the data to the clipboard cache.
406 TRACE("enter format=%d\n", lpFormat->wFormatID);
407 if ( !USER_Driver.pIsSelectionOwner()
408 && USER_Driver.pIsClipboardFormatAvailable( lpFormat->wFormatID ) )
410 if ( !USER_Driver.pGetClipboardData( lpFormat->wFormatID ) )
414 * If Wine owns the clipboard, and the data is marked for delayed render,
417 else if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
419 if( IsWindow(hWndClipOwner) )
421 /* Send a WM_RENDERFORMAT message to notify the owner to render the
422 * data requested into the clipboard.
424 TRACE("Sending WM_RENDERFORMAT message\n");
425 SendMessageW( hWndClipOwner, WM_RENDERFORMAT, (WPARAM)lpFormat->wFormatID, 0 );
429 WARN("\thWndClipOwner (%04x) is lost!\n",
431 CLIPBOARD_ReleaseOwner();
432 lpFormat->wDataPresent = 0;
437 return (lpFormat->hData16 || lpFormat->hData32) ? TRUE : FALSE;
440 /**************************************************************************
441 * CLIPBOARD_ConvertText
442 * Returns number of required/converted characters - not bytes!
444 static INT CLIPBOARD_ConvertText(WORD src_fmt, void const *src, INT src_size,
445 WORD dst_fmt, void *dst, INT dst_size)
449 if(src_fmt == CF_UNICODETEXT)
462 return WideCharToMultiByte(cp, 0, src, src_size, dst, dst_size, NULL, NULL);
465 if(dst_fmt == CF_UNICODETEXT)
478 return MultiByteToWideChar(cp, 0, src, src_size, dst, dst_size);
481 if(!dst_size) return src_size;
483 if(dst_size > src_size) dst_size = src_size;
485 if(src_fmt == CF_TEXT )
486 CharToOemBuffA(src, dst, dst_size);
488 OemToCharBuffA(src, dst, dst_size);
493 /**************************************************************************
494 * CLIPBOARD_RenderText
496 * Renders text to the clipboard buffer converting between UNIX and DOS formats.
498 * RETURNS: pointer to the WINE_CLIPFORMAT if successful, NULL otherwise
500 * FIXME: Should be a pair of driver functions that convert between OEM text and Windows.
503 static LPWINE_CLIPFORMAT CLIPBOARD_RenderText( UINT wFormat )
505 LPWINE_CLIPFORMAT lpSource = ClipFormats;
506 LPWINE_CLIPFORMAT lpTarget = NULL;
507 BOOL foundData = FALSE;
509 /* Asked for CF_TEXT */
510 if( wFormat == CF_TEXT)
512 if(ClipFormats[CF_TEXT-1].wDataPresent)
514 lpSource = &ClipFormats[CF_TEXT-1];
515 lpTarget = &ClipFormats[CF_TEXT-1];
517 TRACE("\t TEXT -> TEXT\n");
519 else if(ClipFormats[CF_UNICODETEXT-1].wDataPresent)
521 /* Convert UNICODETEXT -> TEXT */
522 lpSource = &ClipFormats[CF_UNICODETEXT-1];
523 lpTarget = &ClipFormats[CF_TEXT-1];
525 TRACE("\tUNICODETEXT -> TEXT\n");
527 else if(ClipFormats[CF_OEMTEXT-1].wDataPresent)
529 /* Convert OEMTEXT -> TEXT */
530 lpSource = &ClipFormats[CF_OEMTEXT-1];
531 lpTarget = &ClipFormats[CF_TEXT-1];
533 TRACE("\tOEMTEXT -> TEXT\n");
536 /* Asked for CF_OEMTEXT */
537 else if( wFormat == CF_OEMTEXT)
539 if(ClipFormats[CF_OEMTEXT-1].wDataPresent)
541 lpSource = &ClipFormats[CF_OEMTEXT-1];
542 lpTarget = &ClipFormats[CF_OEMTEXT-1];
544 TRACE("\tOEMTEXT -> OEMTEXT\n");
546 else if(ClipFormats[CF_UNICODETEXT-1].wDataPresent)
548 /* Convert UNICODETEXT -> OEMTEXT */
549 lpSource = &ClipFormats[CF_UNICODETEXT-1];
550 lpTarget = &ClipFormats[CF_OEMTEXT-1];
552 TRACE("\tUNICODETEXT -> OEMTEXT\n");
554 else if(ClipFormats[CF_TEXT-1].wDataPresent)
556 /* Convert TEXT -> OEMTEXT */
557 lpSource = &ClipFormats[CF_TEXT-1];
558 lpTarget = &ClipFormats[CF_OEMTEXT-1];
560 TRACE("\tTEXT -> OEMTEXT\n");
563 /* Asked for CF_UNICODETEXT */
564 else if( wFormat == CF_UNICODETEXT )
566 if(ClipFormats[CF_UNICODETEXT-1].wDataPresent)
568 lpSource = &ClipFormats[CF_UNICODETEXT-1];
569 lpTarget = &ClipFormats[CF_UNICODETEXT-1];
571 TRACE("\tUNICODETEXT -> UNICODETEXT\n");
573 else if(ClipFormats[CF_TEXT-1].wDataPresent)
575 /* Convert TEXT -> UNICODETEXT */
576 lpSource = &ClipFormats[CF_TEXT-1];
577 lpTarget = &ClipFormats[CF_UNICODETEXT-1];
579 TRACE("\tTEXT -> UNICODETEXT\n");
581 else if(ClipFormats[CF_OEMTEXT-1].wDataPresent)
583 /* Convert OEMTEXT -> UNICODETEXT */
584 lpSource = &ClipFormats[CF_OEMTEXT-1];
585 lpTarget = &ClipFormats[CF_UNICODETEXT-1];
587 TRACE("\tOEMTEXT -> UNICODETEXT\n");
592 if ((wFormat == CF_TEXT) || (wFormat == CF_OEMTEXT))
594 lpSource = &ClipFormats[CF_UNICODETEXT-1];
595 lpTarget = __lookup_format( ClipFormats, wFormat );
599 lpSource = __lookup_format( ClipFormats, wFormat );
604 /* First render the source text format */
605 if ( !lpSource || !CLIPBOARD_RenderFormat(lpSource) ) return NULL;
607 /* Convert to the desired target text format, if necessary */
608 if( lpTarget != lpSource && !lpTarget->hData16 && !lpTarget->hData32 )
610 INT src_chars, dst_chars, alloc_size;
614 if (lpSource->hData32)
616 lpstrS = (LPSTR)GlobalLock(lpSource->hData32);
620 lpstrS = (LPSTR)GlobalLock16(lpSource->hData16);
623 if( !lpstrS ) return NULL;
625 /* Text always NULL terminated */
626 if(lpSource->wFormatID == CF_UNICODETEXT)
627 src_chars = strlenW((LPCWSTR)lpstrS)+1;
629 src_chars = strlen(lpstrS)+1;
631 /* Calculate number of characters in the destination buffer */
632 dst_chars = CLIPBOARD_ConvertText(lpSource->wFormatID, lpstrS, src_chars,
633 lpTarget->wFormatID, NULL, 0);
634 if(!dst_chars) return NULL;
636 TRACE("\tconverting from '%s' to '%s', %i chars\n",
637 lpSource->Name, lpTarget->Name, src_chars);
639 /* Convert characters to bytes */
640 if(lpTarget->wFormatID == CF_UNICODETEXT)
641 alloc_size = dst_chars * sizeof(WCHAR);
643 alloc_size = dst_chars;
645 lpTarget->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, alloc_size);
646 lpstrT = (LPSTR)GlobalLock(lpTarget->hData32);
650 CLIPBOARD_ConvertText(lpSource->wFormatID, lpstrS, src_chars,
651 lpTarget->wFormatID, lpstrT, dst_chars);
652 GlobalUnlock(lpTarget->hData32);
655 lpTarget->hData32 = 0;
658 if (lpSource->hData32)
659 GlobalUnlock(lpSource->hData32);
661 GlobalUnlock16(lpSource->hData16);
664 return (lpTarget->hData16 || lpTarget->hData32) ? lpTarget : NULL;
667 /**************************************************************************
668 * CLIPBOARD_EnumClipboardFormats (internal)
670 static UINT CLIPBOARD_EnumClipboardFormats( UINT wFormat )
672 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
675 if (wFormat == 0) /* start from the beginning */
676 lpFormat = ClipFormats;
679 /* walk up to the specified format record */
681 if( !(lpFormat = __lookup_format( lpFormat, wFormat )) )
683 lpFormat = lpFormat->NextFormat; /* right */
688 if (lpFormat == NULL) return 0;
690 if(CLIPBOARD_IsPresent(lpFormat->wFormatID))
693 /* Query the driver if not yet in the cache */
694 if (!USER_Driver.pIsSelectionOwner())
696 if(lpFormat->wFormatID == CF_UNICODETEXT ||
697 lpFormat->wFormatID == CF_TEXT ||
698 lpFormat->wFormatID == CF_OEMTEXT)
700 if(USER_Driver.pIsClipboardFormatAvailable(CF_UNICODETEXT) ||
701 USER_Driver.pIsClipboardFormatAvailable(CF_TEXT) ||
702 USER_Driver.pIsClipboardFormatAvailable(CF_OEMTEXT))
703 bFormatPresent = TRUE;
705 bFormatPresent = FALSE;
708 bFormatPresent = USER_Driver.pIsClipboardFormatAvailable(lpFormat->wFormatID);
714 lpFormat = lpFormat->NextFormat;
717 TRACE("Next available format %d\n", lpFormat->wFormatID);
719 return lpFormat->wFormatID;
723 /**************************************************************************
724 * WIN32 Clipboard implementation
725 **************************************************************************/
727 /**************************************************************************
728 * OpenClipboard (USER32.@)
730 * Note: Netscape uses NULL hWnd to open the clipboard.
732 BOOL WINAPI OpenClipboard( HWND hWnd )
736 TRACE("(%04x)...\n", hWnd);
740 hClipLock = GetCurrentTask();
742 /* Save current user of the clipboard */
743 hWndClipWindow = WIN_GetFullHandle( hWnd );
744 bCBHasChanged = FALSE;
749 TRACE(" returning %i\n", bRet);
754 /**************************************************************************
755 * CloseClipboard (USER.138)
757 BOOL16 WINAPI CloseClipboard16(void)
759 return CloseClipboard();
763 /**************************************************************************
764 * CloseClipboard (USER32.@)
766 BOOL WINAPI CloseClipboard(void)
770 if (hClipLock == GetCurrentTask())
774 if (bCBHasChanged && hWndViewer) SendMessageW( hWndViewer, WM_DRAWCLIPBOARD, 0, 0 );
781 /**************************************************************************
782 * EmptyClipboard (USER.139)
784 BOOL16 WINAPI EmptyClipboard16(void)
786 return EmptyClipboard();
790 /**************************************************************************
791 * EmptyClipboard (USER32.@)
792 * Empties and acquires ownership of the clipboard
794 BOOL WINAPI EmptyClipboard(void)
798 if (hClipLock != GetCurrentTask())
800 WARN("Clipboard not opened by calling task!\n");
804 /* destroy private objects */
806 if (hWndClipOwner) SendMessageW( hWndClipOwner, WM_DESTROYCLIPBOARD, 0, 0 );
808 /* empty the cache */
809 CLIPBOARD_EmptyCache(TRUE);
811 /* Assign ownership of the clipboard to the current client */
812 hWndClipOwner = hWndClipWindow;
814 /* Save the current task */
815 hTaskClipOwner = GetCurrentTask();
817 /* Tell the driver to acquire the selection */
818 USER_Driver.pAcquireClipboard();
824 /**************************************************************************
825 * GetClipboardOwner (USER32.@)
826 * FIXME: Can't return the owner if the clipbard is owned by an external app
828 HWND WINAPI GetClipboardOwner(void)
831 return hWndClipOwner;
835 /**************************************************************************
836 * SetClipboardData (USER.141)
838 HANDLE16 WINAPI SetClipboardData16( UINT16 wFormat, HANDLE16 hData )
840 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
842 TRACE("(%04X, %04x) !\n", wFormat, hData);
844 /* NOTE: If the hData is zero and current owner doesn't match
845 * the window that opened the clipboard then this application
846 * is screwed because WM_RENDERFORMAT will go to the owner.
847 * (to become the owner it must call EmptyClipboard() before
851 if( CLIPBOARD_IsLocked() || !lpFormat ||
852 (!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) )
854 WARN("Invalid hData or clipboard not opened by calling task!\n");
858 /* Pass on the request to the driver */
859 USER_Driver.pSetClipboardData(wFormat);
861 if ( lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32 )
863 CLIPBOARD_DeleteRecord(lpFormat, TRUE);
865 /* delete existing CF_UNICODETEXT/CF_TEXT/CF_OEMTEXT aliases */
866 if(wFormat == CF_UNICODETEXT)
868 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
869 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
871 else if(wFormat == CF_TEXT)
873 CLIPBOARD_DeleteRecord(&ClipFormats[CF_UNICODETEXT-1], TRUE);
874 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
876 else if(wFormat == CF_OEMTEXT)
878 CLIPBOARD_DeleteRecord(&ClipFormats[CF_UNICODETEXT-1], TRUE);
879 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
883 bCBHasChanged = TRUE;
884 lpFormat->wDataPresent = 1;
885 lpFormat->hData16 = hData; /* 0 is legal, see WM_RENDERFORMAT */
886 lpFormat->hData32 = 0;
888 return lpFormat->hData16;
892 /**************************************************************************
893 * SetClipboardData (USER32.@)
895 HANDLE WINAPI SetClipboardData( UINT wFormat, HANDLE hData )
897 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
899 TRACE("(%08X, %08x) !\n", wFormat, hData);
901 /* NOTE: If the hData is zero and current owner doesn't match
902 * the window that opened the clipboard then this application
903 * is screwed because WM_RENDERFORMAT will go to the owner.
904 * (to become the owner it must call EmptyClipboard() before
908 if( CLIPBOARD_IsLocked() || !lpFormat ||
909 (!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) )
911 WARN("Invalid hData or clipboard not opened by calling task!\n");
915 /* Tell the driver to acquire the selection */
916 USER_Driver.pAcquireClipboard();
918 if ( lpFormat->wDataPresent &&
919 (lpFormat->hData16 || lpFormat->hData32) )
921 CLIPBOARD_DeleteRecord(lpFormat, TRUE);
923 /* delete existing CF_UNICODETEXT/CF_TEXT/CF_OEMTEXT aliases */
924 if(wFormat == CF_UNICODETEXT)
926 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
927 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
929 else if(wFormat == CF_TEXT)
931 CLIPBOARD_DeleteRecord(&ClipFormats[CF_UNICODETEXT-1], TRUE);
932 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
934 else if(wFormat == CF_OEMTEXT)
936 CLIPBOARD_DeleteRecord(&ClipFormats[CF_UNICODETEXT-1], TRUE);
937 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
941 bCBHasChanged = TRUE;
942 lpFormat->wDataPresent = 1;
943 lpFormat->hDataSrc32 = hData; /* Save the source handle */
946 * Make a shared duplicate if the memory is not shared
947 * TODO: What should be done for non-memory objects
949 if ( CLIPBOARD_IsMemoryObject(wFormat) && hData && !(GlobalFlags(hData) & GMEM_DDESHARE) )
950 lpFormat->hData32 = CLIPBOARD_GlobalDupMem( hData );
952 lpFormat->hData32 = hData; /* 0 is legal, see WM_RENDERFORMAT */
954 lpFormat->hData16 = 0;
956 return lpFormat->hData32; /* Should we return lpFormat->hDataSrc32 */
960 /**************************************************************************
961 * GetClipboardData (USER.142)
963 HANDLE16 WINAPI GetClipboardData16( UINT16 wFormat )
965 LPWINE_CLIPFORMAT lpRender = ClipFormats;
967 TRACE("(%04X)\n", wFormat);
969 if (CLIPBOARD_IsLocked())
971 WARN("Clipboard not opened by calling task!\n");
975 if( wFormat == CF_UNICODETEXT || wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
977 lpRender = CLIPBOARD_RenderText(wFormat);
978 if ( !lpRender ) return 0;
982 lpRender = __lookup_format( ClipFormats, wFormat );
983 if( !lpRender || !CLIPBOARD_RenderFormat(lpRender) ) return 0;
986 /* Convert between 32 -> 16 bit data, if necessary */
987 if( lpRender->hData32 && !lpRender->hData16
988 && CLIPBOARD_IsMemoryObject(wFormat) )
991 if( lpRender->wFormatID == CF_METAFILEPICT )
992 size = sizeof( METAFILEPICT16 );
994 size = GlobalSize(lpRender->hData32);
996 lpRender->hData16 = GlobalAlloc16(GMEM_ZEROINIT, size);
997 if( !lpRender->hData16 )
998 ERR("(%04X) -- not enough memory in 16b heap\n", wFormat);
1001 if( lpRender->wFormatID == CF_METAFILEPICT )
1003 FIXME("\timplement function CopyMetaFilePict32to16\n");
1004 FIXME("\tin the appropriate file.\n");
1005 #ifdef SOMEONE_IMPLEMENTED_ME
1006 CopyMetaFilePict32to16( GlobalLock16(lpRender->hData16),
1007 GlobalLock(lpRender->hData32) );
1012 memcpy( GlobalLock16(lpRender->hData16),
1013 GlobalLock(lpRender->hData32),
1016 GlobalUnlock16(lpRender->hData16);
1017 GlobalUnlock(lpRender->hData32);
1021 TRACE("\treturning %04x (type %i)\n",
1022 lpRender->hData16, lpRender->wFormatID);
1023 return lpRender->hData16;
1027 /**************************************************************************
1028 * GetClipboardData (USER32.@)
1030 HANDLE WINAPI GetClipboardData( UINT wFormat )
1032 LPWINE_CLIPFORMAT lpRender = ClipFormats;
1034 TRACE("(%08X)\n", wFormat);
1036 if (CLIPBOARD_IsLocked())
1038 WARN("Clipboard not opened by calling task!\n");
1042 if( wFormat == CF_UNICODETEXT || wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
1044 lpRender = CLIPBOARD_RenderText(wFormat);
1045 if ( !lpRender ) return 0;
1049 lpRender = __lookup_format( ClipFormats, wFormat );
1050 if( !lpRender || !CLIPBOARD_RenderFormat(lpRender) ) return 0;
1053 /* Convert between 16 -> 32 bit data, if necessary */
1054 if( lpRender->hData16 && !lpRender->hData32
1055 && CLIPBOARD_IsMemoryObject(wFormat) )
1058 if( lpRender->wFormatID == CF_METAFILEPICT )
1059 size = sizeof( METAFILEPICT );
1061 size = GlobalSize16(lpRender->hData16);
1062 lpRender->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE,
1064 if( lpRender->wFormatID == CF_METAFILEPICT )
1066 FIXME("\timplement function CopyMetaFilePict16to32\n");
1067 FIXME("\tin the appropriate file.\n");
1068 #ifdef SOMEONE_IMPLEMENTED_ME
1069 CopyMetaFilePict16to32( GlobalLock16(lpRender->hData32),
1070 GlobalLock(lpRender->hData16) );
1075 memcpy( GlobalLock(lpRender->hData32),
1076 GlobalLock16(lpRender->hData16),
1079 GlobalUnlock(lpRender->hData32);
1080 GlobalUnlock16(lpRender->hData16);
1083 TRACE("\treturning %04x (type %i)\n",
1084 lpRender->hData32, lpRender->wFormatID);
1085 return lpRender->hData32;
1089 /**************************************************************************
1090 * CountClipboardFormats (USER.143)
1092 INT16 WINAPI CountClipboardFormats16(void)
1094 return CountClipboardFormats();
1098 /**************************************************************************
1099 * CountClipboardFormats (USER32.@)
1101 INT WINAPI CountClipboardFormats(void)
1103 INT FormatCount = 0;
1104 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
1110 if (lpFormat == NULL) break;
1112 if( lpFormat->wFormatID != CF_TEXT ) /* Don't count CF_TEXT */
1115 * The format is available if either:
1116 * 1. The data is already in the cache.
1117 * 2. The selection is not owned by us(WINE) and the data is
1118 * available to the clipboard driver.
1120 if ( lpFormat->wDataPresent ||
1121 ( !USER_Driver.pIsSelectionOwner()
1122 && USER_Driver.pIsClipboardFormatAvailable( lpFormat->wFormatID ) ) )
1124 TRACE("\tdata found for format 0x%04x(%s)\n",
1125 lpFormat->wFormatID, CLIPBOARD_GetFormatName(lpFormat->wFormatID));
1130 lpFormat = lpFormat->NextFormat;
1133 /* these are equivalent, adjust the total */
1134 FormatCount += (ClipFormats[CF_UNICODETEXT-1].wDataPresent ||
1135 ClipFormats[CF_TEXT-1].wDataPresent ||
1136 ClipFormats[CF_OEMTEXT-1].wDataPresent) ? 1 : 0;
1138 TRACE("\ttotal %d\n", FormatCount);
1142 /**************************************************************************
1143 * EnumClipboardFormats (USER.144)
1145 UINT16 WINAPI EnumClipboardFormats16( UINT16 wFormat )
1147 return EnumClipboardFormats( wFormat );
1151 /**************************************************************************
1152 * EnumClipboardFormats (USER32.@)
1154 UINT WINAPI EnumClipboardFormats( UINT wFormat )
1156 TRACE("(%04X)\n", wFormat);
1158 if (CLIPBOARD_IsLocked())
1160 WARN("Clipboard not opened by calling task!\n");
1164 return CLIPBOARD_EnumClipboardFormats(wFormat);
1168 /**************************************************************************
1169 * RegisterClipboardFormatA (USER32.@)
1171 UINT WINAPI RegisterClipboardFormatA( LPCSTR FormatName )
1173 LPWINE_CLIPFORMAT lpNewFormat;
1174 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
1176 if (FormatName == NULL) return 0;
1178 TRACE("('%s') !\n", FormatName);
1180 /* walk format chain to see if it's already registered */
1184 if ( !strcmp(lpFormat->Name,FormatName) )
1186 lpFormat->wRefCount++;
1187 return lpFormat->wFormatID;
1190 if ( lpFormat->NextFormat == NULL ) break;
1192 lpFormat = lpFormat->NextFormat;
1195 /* allocate storage for new format entry */
1197 lpNewFormat = (LPWINE_CLIPFORMAT)HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_CLIPFORMAT));
1198 if(lpNewFormat == NULL) {
1199 WARN("No more memory for a new format!\n");
1202 lpFormat->NextFormat = lpNewFormat;
1203 lpNewFormat->wFormatID = LastRegFormat;
1204 lpNewFormat->wRefCount = 1;
1206 if (!(lpNewFormat->Name = HeapAlloc(GetProcessHeap(), 0, strlen(FormatName)+1 )))
1208 WARN("No more memory for the new format name!\n");
1209 HeapFree(GetProcessHeap(), 0, lpNewFormat);
1212 strcpy( lpNewFormat->Name, FormatName );
1214 lpNewFormat->wDataPresent = 0;
1215 lpNewFormat->hData16 = 0;
1216 lpNewFormat->hDataSrc32 = 0;
1217 lpNewFormat->hData32 = 0;
1218 lpNewFormat->drvData = 0;
1219 lpNewFormat->PrevFormat = lpFormat;
1220 lpNewFormat->NextFormat = NULL;
1222 /* Pass on the registration request to the driver */
1223 USER_Driver.pRegisterClipboardFormat( FormatName );
1225 return LastRegFormat++;
1229 /**************************************************************************
1230 * RegisterClipboardFormat (USER.145)
1232 UINT16 WINAPI RegisterClipboardFormat16( LPCSTR FormatName )
1234 return RegisterClipboardFormatA( FormatName );
1238 /**************************************************************************
1239 * RegisterClipboardFormatW (USER32.@)
1241 UINT WINAPI RegisterClipboardFormatW( LPCWSTR formatName )
1243 LPSTR aFormat = HEAP_strdupWtoA( GetProcessHeap(), 0, formatName );
1244 UINT ret = RegisterClipboardFormatA( aFormat );
1245 HeapFree( GetProcessHeap(), 0, aFormat );
1250 /**************************************************************************
1251 * GetClipboardFormatName (USER.146)
1253 INT16 WINAPI GetClipboardFormatName16( UINT16 wFormat, LPSTR retStr, INT16 maxlen )
1255 return GetClipboardFormatNameA( wFormat, retStr, maxlen );
1259 /**************************************************************************
1260 * GetClipboardFormatNameA (USER32.@)
1262 INT WINAPI GetClipboardFormatNameA( UINT wFormat, LPSTR retStr, INT maxlen )
1264 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
1266 TRACE("(%04X, %p, %d) !\n", wFormat, retStr, maxlen);
1268 if (lpFormat == NULL || lpFormat->Name == NULL ||
1269 lpFormat->wFormatID < CF_REGFORMATBASE) return 0;
1271 TRACE("Name='%s' !\n", lpFormat->Name);
1273 lstrcpynA( retStr, lpFormat->Name, maxlen );
1274 return strlen(retStr);
1278 /**************************************************************************
1279 * GetClipboardFormatNameW (USER32.@)
1281 INT WINAPI GetClipboardFormatNameW( UINT wFormat, LPWSTR retStr, INT maxlen )
1284 LPSTR p = HeapAlloc( GetProcessHeap(), 0, maxlen );
1285 if(p == NULL) return 0; /* FIXME: is this the correct failure value? */
1287 ret = GetClipboardFormatNameA( wFormat, p, maxlen );
1289 if (maxlen > 0 && !MultiByteToWideChar( CP_ACP, 0, p, -1, retStr, maxlen ))
1290 retStr[maxlen-1] = 0;
1291 HeapFree( GetProcessHeap(), 0, p );
1296 /**************************************************************************
1297 * SetClipboardViewer (USER32.@)
1299 HWND WINAPI SetClipboardViewer( HWND hWnd )
1301 HWND hwndPrev = hWndViewer;
1303 TRACE("(%04x): returning %04x\n", hWnd, hwndPrev);
1305 hWndViewer = WIN_GetFullHandle( hWnd );
1310 /**************************************************************************
1311 * GetClipboardViewer (USER32.@)
1313 HWND WINAPI GetClipboardViewer(void)
1320 /**************************************************************************
1321 * ChangeClipboardChain (USER32.@)
1323 BOOL WINAPI ChangeClipboardChain(HWND hWnd, HWND hWndNext)
1327 FIXME("(0x%04x, 0x%04x): stub?\n", hWnd, hWndNext);
1330 bRet = !SendMessageW( hWndViewer, WM_CHANGECBCHAIN, (WPARAM)hWnd, (LPARAM)hWndNext );
1332 WARN("hWndViewer is lost\n");
1334 if( WIN_GetFullHandle(hWnd) == hWndViewer ) hWndViewer = WIN_GetFullHandle( hWndNext );
1340 /**************************************************************************
1341 * IsClipboardFormatAvailable (USER.193)
1343 BOOL16 WINAPI IsClipboardFormatAvailable16( UINT16 wFormat )
1345 return IsClipboardFormatAvailable( wFormat );
1349 /**************************************************************************
1350 * IsClipboardFormatAvailable (USER32.@)
1352 BOOL WINAPI IsClipboardFormatAvailable( UINT wFormat )
1356 if (wFormat == 0) /* Reject this case quickly */
1360 UINT iret = CLIPBOARD_EnumClipboardFormats(wFormat - 1);
1361 if ((wFormat == CF_TEXT) || (wFormat == CF_OEMTEXT) || (wFormat == CF_UNICODETEXT))
1362 bRet = ((iret == CF_TEXT) || (iret == CF_OEMTEXT) || (iret == CF_UNICODETEXT));
1364 bRet = iret == wFormat;
1366 TRACE("(%04X)- ret(%d)\n", wFormat, bRet);
1371 /**************************************************************************
1372 * GetOpenClipboardWindow (USER32.@)
1373 * FIXME: This wont work if an external app owns the selection
1375 HWND WINAPI GetOpenClipboardWindow(void)
1378 return hWndClipWindow;
1382 /**************************************************************************
1383 * GetPriorityClipboardFormat (USER32.@)
1385 INT WINAPI GetPriorityClipboardFormat( UINT *list, INT nCount )
1390 if(CountClipboardFormats() == 0) return 0;
1392 for (i = 0; i < nCount; i++)
1393 if (IsClipboardFormatAvailable( list[i] )) return list[i];
1398 /**************************************************************************
1399 * GetClipboardSequenceNumber (USER32.@)
1400 * Supported on Win2k/Win98
1401 * MSDN: Windows clipboard code keeps a serial number for the clipboard
1402 * for each window station. The number is incremented whenever the
1403 * contents change or are emptied.
1404 * If you do not have WINSTA_ACCESSCLIPBOARD then the function returns 0
1406 DWORD WINAPI GetClipboardSequenceNumber(VOID)
1408 FIXME("Returning 0, see windows/clipboard.c\n");
1409 /* FIXME: Use serial numbers */