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 "wine/port.h"
35 #include <sys/types.h>
46 #include "wine/winuser16.h"
47 #include "wine/winbase16.h"
51 #include "clipboard.h"
53 #include "wine/debug.h"
54 #include "wine/unicode.h"
56 WINE_DEFAULT_DEBUG_CHANNEL(clipboard
);
58 #define CF_REGFORMATBASE 0xC000
60 #define HGDIOBJ_32(handle16) ((HGDIOBJ)(ULONG_PTR)(handle16))
62 /**************************************************************************
63 * Clipboard context global variables
66 static DWORD ClipLock
= 0;
67 static BOOL bCBHasChanged
= FALSE
;
69 static HWND hWndClipWindow
; /* window that last opened clipboard */
70 static HWND hWndClipOwner
; /* current clipboard owner */
71 static DWORD ClipOwner
; /* clipboard owner's thread id */
72 static HWND hWndViewer
; /* start of viewers chain */
74 /* Clipboard cache initial data.
75 * WARNING: This data ordering is dependent on the WINE_CLIPFORMAT structure
76 * declared in clipboard.h
78 WINE_CLIPFORMAT ClipFormats
[] = {
79 { CF_TEXT
, 1, 0, "Text", 0, 0, 0, 0, NULL
, &ClipFormats
[1]},
80 { CF_BITMAP
, 1, 0, "Bitmap", 0, 0, 0, 0, &ClipFormats
[0], &ClipFormats
[2]},
81 { CF_METAFILEPICT
, 1, 0, "MetaFile Picture", 0, 0, 0, 0, &ClipFormats
[1], &ClipFormats
[3]},
82 { CF_SYLK
, 1, 0, "Sylk", 0, 0, 0, 0, &ClipFormats
[2], &ClipFormats
[4]},
83 { CF_DIF
, 1, 0, "DIF", 0, 0, 0, 0, &ClipFormats
[3], &ClipFormats
[5]},
84 { CF_TIFF
, 1, 0, "TIFF", 0, 0, 0, 0, &ClipFormats
[4], &ClipFormats
[6]},
85 { CF_OEMTEXT
, 1, 0, "OEM Text", 0, 0, 0, 0, &ClipFormats
[5], &ClipFormats
[7]},
86 { CF_DIB
, 1, 0, "DIB", 0, 0, 0, 0, &ClipFormats
[6], &ClipFormats
[8]},
87 { CF_PALETTE
, 1, 0, "Palette", 0, 0, 0, 0, &ClipFormats
[7], &ClipFormats
[9]},
88 { CF_PENDATA
, 1, 0, "PenData", 0, 0, 0, 0, &ClipFormats
[8], &ClipFormats
[10]},
89 { CF_RIFF
, 1, 0, "RIFF", 0, 0, 0, 0, &ClipFormats
[9], &ClipFormats
[11]},
90 { CF_WAVE
, 1, 0, "Wave", 0, 0, 0, 0, &ClipFormats
[10], &ClipFormats
[12]},
91 { CF_UNICODETEXT
, 1, 0, "Unicode Text", 0, 0, 0, 0, &ClipFormats
[11], &ClipFormats
[13]},
92 { CF_OWNERDISPLAY
, 1, 0, "Owner Display", 0, 0, 0, 0, &ClipFormats
[12], &ClipFormats
[14]},
93 { CF_DSPTEXT
, 1, 0, "DSPText", 0, 0, 0, 0, &ClipFormats
[13], &ClipFormats
[15]},
94 { CF_DSPMETAFILEPICT
, 1, 0, "DSPMetaFile Picture", 0, 0, 0, 0, &ClipFormats
[14], &ClipFormats
[16]},
95 { CF_DSPBITMAP
, 1, 0, "DSPBitmap", 0, 0, 0, 0, &ClipFormats
[15], &ClipFormats
[17]},
96 { CF_HDROP
, 1, 0, "HDROP", 0, 0, 0, 0, &ClipFormats
[16], &ClipFormats
[18]},
97 { CF_ENHMETAFILE
, 1, 0, "Enhmetafile", 0, 0, 0, 0, &ClipFormats
[17], NULL
}
101 /**************************************************************************
102 * Internal Clipboard implementation methods
103 **************************************************************************/
106 /**************************************************************************
107 * CLIPBOARD_LookupFormat
109 static LPWINE_CLIPFORMAT
__lookup_format( LPWINE_CLIPFORMAT lpFormat
, WORD wID
)
113 if (lpFormat
== NULL
||
114 lpFormat
->wFormatID
== wID
) break;
115 lpFormat
= lpFormat
->NextFormat
;
120 LPWINE_CLIPFORMAT
CLIPBOARD_LookupFormat( WORD wID
)
122 return __lookup_format( ClipFormats
, wID
);
125 /**************************************************************************
127 * Check if the clipboard cache is available to the caller
129 BOOL
CLIPBOARD_IsLocked()
131 BOOL bIsLocked
= TRUE
;
134 * The clipboard is available:
135 * 1. if the caller's task has opened the clipboard,
137 * 2. if the caller is the clipboard owners task, AND is responding to a
138 * WM_RENDERFORMAT message.
140 if ( ClipLock
== GetCurrentThreadId() )
143 else if ( ClipOwner
== GetCurrentThreadId() )
145 /* Check if we're currently executing inside a window procedure
146 * called in response to a WM_RENDERFORMAT message. A WM_RENDERFORMAT
147 * handler is not permitted to open the clipboard since it has been opened
148 * by another client. However the handler must have access to the
149 * clipboard in order to update data in response to this message.
152 MESSAGEQUEUE
*queue
= QUEUE_Current();
156 && queue
->smWaiting
->msg
== WM_RENDERFORMAT
157 && queue
->smWaiting
->hSrcQueue
161 /* FIXME: queue check no longer possible */
169 /**************************************************************************
170 * CLIPBOARD_ReleaseOwner
171 * Gives up ownership of the clipboard
173 void CLIPBOARD_ReleaseOwner()
179 /**************************************************************************
180 * CLIPBOARD_GlobalFreeProc
182 * This is a callback mechanism to allow HGLOBAL data to be released in
183 * the context of the process which allocated it. We post a WM_TIMER message
184 * to the owner window(in CLIPBOARD_DeleteRecord) and destroy the data(in idEvent)
185 * in this WndProc, which is invoked when the apps message loop calls DispatchMessage.
186 * This technique is discussed in Matt Pietrek's "Under the Hood".
187 * An article describing the same may be found in MSDN by searching for WM_TIMER.
188 * Note that this mechanism will probably stop working when WINE supports
189 * address space separation. When "queue events" are implemented in Wine we
190 * should switch to using that mechanism, since it is more robust and does not
191 * require a procedure address to be passed. See the SetWinEventHook API for
194 VOID CALLBACK
CLIPBOARD_GlobalFreeProc( HWND hwnd
, UINT uMsg
, UINT idEvent
, DWORD dwTime
)
196 /* idEvent is the HGLOBAL to be deleted */
197 GlobalFree( (HGLOBAL
)idEvent
);
200 /**************************************************************************
201 * CLIPBOARD_DeleteRecord
203 void CLIPBOARD_DeleteRecord(LPWINE_CLIPFORMAT lpFormat
, BOOL bChange
)
205 if( (lpFormat
->wFormatID
>= CF_GDIOBJFIRST
&&
206 lpFormat
->wFormatID
<= CF_GDIOBJLAST
) || lpFormat
->wFormatID
== CF_BITMAP
207 || lpFormat
->wFormatID
== CF_PALETTE
)
209 if (lpFormat
->hData32
)
210 DeleteObject(lpFormat
->hData32
);
211 if (lpFormat
->hData16
)
212 DeleteObject(HGDIOBJ_32(lpFormat
->hData16
));
214 else if( lpFormat
->wFormatID
== CF_METAFILEPICT
)
216 if (lpFormat
->hData32
)
218 DeleteMetaFile( ((METAFILEPICT
*)GlobalLock( lpFormat
->hData32
))->hMF
);
219 PostMessageA(hWndClipOwner
, WM_TIMER
,
220 (WPARAM
)lpFormat
->hData32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
221 if (lpFormat
->hDataSrc32
)
223 /* Release lpFormat->hData32 in the context of the process which created it.
224 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
225 * GlobalFree(lpFormat->hDataSrc32);
227 PostMessageA(hWndClipOwner
, WM_TIMER
,
228 (WPARAM
)lpFormat
->hDataSrc32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
231 if (lpFormat
->hData16
)
232 /* HMETAFILE16 and HMETAFILE32 are apparently the same thing,
233 and a shallow copy is enough to share a METAFILEPICT
234 structure between 16bit and 32bit clipboards. The MetaFile
235 should of course only be deleted once. */
236 GlobalFree16(lpFormat
->hData16
);
238 if (lpFormat
->hData16
)
240 DeleteMetaFile16( ((METAFILEPICT16
*)GlobalLock16( lpFormat
->hData16
))->hMF
);
241 GlobalFree16(lpFormat
->hData16
);
246 if (lpFormat
->hData32
)
248 /* Release lpFormat->hData32 in the context of the process which created it.
249 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
250 * GlobalFree( lpFormat->hData32 );
252 PostMessageA(hWndClipOwner
, WM_TIMER
,
253 (WPARAM
)lpFormat
->hData32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
255 if (lpFormat
->hDataSrc32
)
257 /* Release lpFormat->hData32 in the context of the process which created it.
258 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
259 * GlobalFree(lpFormat->hDataSrc32);
261 PostMessageA(hWndClipOwner
, WM_TIMER
,
262 (WPARAM
)lpFormat
->hDataSrc32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
264 if (lpFormat
->hData16
)
265 GlobalFree16(lpFormat
->hData16
);
268 lpFormat
->wDataPresent
= 0;
269 lpFormat
->hData16
= 0;
270 lpFormat
->hData32
= 0;
271 lpFormat
->hDataSrc32
= 0;
272 lpFormat
->drvData
= 0;
274 if( bChange
) bCBHasChanged
= TRUE
;
277 /**************************************************************************
278 * CLIPBOARD_EmptyCache
280 void CLIPBOARD_EmptyCache( BOOL bChange
)
282 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
286 if ( lpFormat
->wDataPresent
|| lpFormat
->hData16
|| lpFormat
->hData32
)
287 CLIPBOARD_DeleteRecord( lpFormat
, bChange
);
289 lpFormat
= lpFormat
->NextFormat
;
293 /**************************************************************************
294 * CLIPBOARD_IsPresent
296 BOOL
CLIPBOARD_IsPresent(WORD wFormat
)
300 if( wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
|| wFormat
== CF_UNICODETEXT
)
301 return ClipFormats
[CF_TEXT
-1].wDataPresent
||
302 ClipFormats
[CF_OEMTEXT
-1].wDataPresent
||
303 ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
;
306 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
307 if( lpFormat
) return (lpFormat
->wDataPresent
);
312 /**************************************************************************
313 * CLIPBOARD_IsCacheRendered
314 * Checks if any data needs to be rendered to the clipboard cache
316 * TRUE - All clipboard data is available in the cache
317 * FALSE - Some data is marked for delayed render and needs rendering
319 BOOL
CLIPBOARD_IsCacheRendered()
321 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
323 /* check if all formats were rendered */
326 if( lpFormat
->wDataPresent
&& !lpFormat
->hData16
&& !lpFormat
->hData32
)
329 lpFormat
= lpFormat
->NextFormat
;
336 /**************************************************************************
337 * CLIPBOARD_IsMemoryObject
338 * Tests if the clipboard format specifies a memory object
340 BOOL
CLIPBOARD_IsMemoryObject( WORD wFormat
)
345 case CF_METAFILEPICT
:
357 /***********************************************************************
358 * CLIPBOARD_GlobalDupMem( HGLOBAL )
359 * Helper method to duplicate an HGLOBAL chunk of memory into shared memory
361 HGLOBAL
CLIPBOARD_GlobalDupMem( HGLOBAL hGlobalSrc
)
364 PVOID pGlobalSrc
, pGlobalDest
;
370 cBytes
= GlobalSize(hGlobalSrc
);
374 /* Turn on the DDESHARE and _MOVEABLE flags explicitly */
375 hGlobalDest
= GlobalAlloc( GlobalFlags(hGlobalSrc
) | GMEM_DDESHARE
| GMEM_MOVEABLE
,
380 pGlobalSrc
= GlobalLock(hGlobalSrc
);
381 pGlobalDest
= GlobalLock(hGlobalDest
);
382 if ( !pGlobalSrc
|| !pGlobalDest
)
385 memcpy(pGlobalDest
, pGlobalSrc
, cBytes
);
387 GlobalUnlock(hGlobalSrc
);
388 GlobalUnlock(hGlobalDest
);
393 /**************************************************************************
394 * CLIPBOARD_GetFormatName
395 * Gets the format name associated with an ID
397 char * CLIPBOARD_GetFormatName(UINT wFormat
, LPSTR buf
, INT size
)
399 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
405 strncpy(buf
, lpFormat
->Name
, size
);
409 return lpFormat
->Name
;
416 /**************************************************************************
417 * CLIPBOARD_RenderFormat
419 static BOOL
CLIPBOARD_RenderFormat(LPWINE_CLIPFORMAT lpFormat
)
422 * If WINE is not the selection owner, and the format is available
423 * we must ask the driver to render the data to the clipboard cache.
425 TRACE("enter format=%d\n", lpFormat
->wFormatID
);
426 if ( !USER_Driver
.pIsSelectionOwner()
427 && USER_Driver
.pIsClipboardFormatAvailable( lpFormat
->wFormatID
) )
429 if ( !USER_Driver
.pGetClipboardData( lpFormat
->wFormatID
) )
433 * If Wine owns the clipboard, and the data is marked for delayed render,
436 else if( lpFormat
->wDataPresent
&& !lpFormat
->hData16
&& !lpFormat
->hData32
)
438 if( IsWindow(hWndClipOwner
) )
440 /* Send a WM_RENDERFORMAT message to notify the owner to render the
441 * data requested into the clipboard.
443 TRACE("Sending WM_RENDERFORMAT message\n");
444 SendMessageW( hWndClipOwner
, WM_RENDERFORMAT
, (WPARAM
)lpFormat
->wFormatID
, 0 );
448 WARN("\thWndClipOwner (%p) is lost!\n", hWndClipOwner
);
449 CLIPBOARD_ReleaseOwner();
450 lpFormat
->wDataPresent
= 0;
455 return (lpFormat
->hData16
|| lpFormat
->hData32
) ? TRUE
: FALSE
;
458 /**************************************************************************
459 * CLIPBOARD_ConvertText
460 * Returns number of required/converted characters - not bytes!
462 static INT
CLIPBOARD_ConvertText(WORD src_fmt
, void const *src
, INT src_size
,
463 WORD dst_fmt
, void *dst
, INT dst_size
)
467 if(src_fmt
== CF_UNICODETEXT
)
480 return WideCharToMultiByte(cp
, 0, src
, src_size
, dst
, dst_size
, NULL
, NULL
);
483 if(dst_fmt
== CF_UNICODETEXT
)
496 return MultiByteToWideChar(cp
, 0, src
, src_size
, dst
, dst_size
);
499 if(!dst_size
) return src_size
;
501 if(dst_size
> src_size
) dst_size
= src_size
;
503 if(src_fmt
== CF_TEXT
)
504 CharToOemBuffA(src
, dst
, dst_size
);
506 OemToCharBuffA(src
, dst
, dst_size
);
511 /**************************************************************************
512 * CLIPBOARD_RenderText
514 * Renders text to the clipboard buffer converting between UNIX and DOS formats.
516 * RETURNS: pointer to the WINE_CLIPFORMAT if successful, NULL otherwise
518 * FIXME: Should be a pair of driver functions that convert between OEM text and Windows.
521 static LPWINE_CLIPFORMAT
CLIPBOARD_RenderText( UINT wFormat
)
523 LPWINE_CLIPFORMAT lpSource
= ClipFormats
;
524 LPWINE_CLIPFORMAT lpTarget
= NULL
;
525 BOOL foundData
= FALSE
;
527 /* Asked for CF_TEXT */
528 if( wFormat
== CF_TEXT
)
530 if(ClipFormats
[CF_TEXT
-1].wDataPresent
)
532 lpSource
= &ClipFormats
[CF_TEXT
-1];
533 lpTarget
= &ClipFormats
[CF_TEXT
-1];
535 TRACE("\t TEXT -> TEXT\n");
537 else if(ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
)
539 /* Convert UNICODETEXT -> TEXT */
540 lpSource
= &ClipFormats
[CF_UNICODETEXT
-1];
541 lpTarget
= &ClipFormats
[CF_TEXT
-1];
543 TRACE("\tUNICODETEXT -> TEXT\n");
545 else if(ClipFormats
[CF_OEMTEXT
-1].wDataPresent
)
547 /* Convert OEMTEXT -> TEXT */
548 lpSource
= &ClipFormats
[CF_OEMTEXT
-1];
549 lpTarget
= &ClipFormats
[CF_TEXT
-1];
551 TRACE("\tOEMTEXT -> TEXT\n");
554 /* Asked for CF_OEMTEXT */
555 else if( wFormat
== CF_OEMTEXT
)
557 if(ClipFormats
[CF_OEMTEXT
-1].wDataPresent
)
559 lpSource
= &ClipFormats
[CF_OEMTEXT
-1];
560 lpTarget
= &ClipFormats
[CF_OEMTEXT
-1];
562 TRACE("\tOEMTEXT -> OEMTEXT\n");
564 else if(ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
)
566 /* Convert UNICODETEXT -> OEMTEXT */
567 lpSource
= &ClipFormats
[CF_UNICODETEXT
-1];
568 lpTarget
= &ClipFormats
[CF_OEMTEXT
-1];
570 TRACE("\tUNICODETEXT -> OEMTEXT\n");
572 else if(ClipFormats
[CF_TEXT
-1].wDataPresent
)
574 /* Convert TEXT -> OEMTEXT */
575 lpSource
= &ClipFormats
[CF_TEXT
-1];
576 lpTarget
= &ClipFormats
[CF_OEMTEXT
-1];
578 TRACE("\tTEXT -> OEMTEXT\n");
581 /* Asked for CF_UNICODETEXT */
582 else if( wFormat
== CF_UNICODETEXT
)
584 if(ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
)
586 lpSource
= &ClipFormats
[CF_UNICODETEXT
-1];
587 lpTarget
= &ClipFormats
[CF_UNICODETEXT
-1];
589 TRACE("\tUNICODETEXT -> UNICODETEXT\n");
591 else if(ClipFormats
[CF_TEXT
-1].wDataPresent
)
593 /* Convert TEXT -> UNICODETEXT */
594 lpSource
= &ClipFormats
[CF_TEXT
-1];
595 lpTarget
= &ClipFormats
[CF_UNICODETEXT
-1];
597 TRACE("\tTEXT -> UNICODETEXT\n");
599 else if(ClipFormats
[CF_OEMTEXT
-1].wDataPresent
)
601 /* Convert OEMTEXT -> UNICODETEXT */
602 lpSource
= &ClipFormats
[CF_OEMTEXT
-1];
603 lpTarget
= &ClipFormats
[CF_UNICODETEXT
-1];
605 TRACE("\tOEMTEXT -> UNICODETEXT\n");
610 if ((wFormat
== CF_TEXT
) || (wFormat
== CF_OEMTEXT
))
612 lpSource
= &ClipFormats
[CF_UNICODETEXT
-1];
613 lpTarget
= __lookup_format( ClipFormats
, wFormat
);
617 lpSource
= __lookup_format( ClipFormats
, wFormat
);
622 /* First render the source text format */
623 if ( !lpSource
|| !CLIPBOARD_RenderFormat(lpSource
) ) return NULL
;
625 /* Convert to the desired target text format, if necessary */
626 if( lpTarget
!= lpSource
&& !lpTarget
->hData16
&& !lpTarget
->hData32
)
628 INT src_chars
, dst_chars
, alloc_size
;
632 if (lpSource
->hData32
)
634 lpstrS
= (LPSTR
)GlobalLock(lpSource
->hData32
);
638 lpstrS
= (LPSTR
)GlobalLock16(lpSource
->hData16
);
641 if( !lpstrS
) return NULL
;
643 /* Text always NULL terminated */
644 if(lpSource
->wFormatID
== CF_UNICODETEXT
)
645 src_chars
= strlenW((LPCWSTR
)lpstrS
)+1;
647 src_chars
= strlen(lpstrS
)+1;
649 /* Calculate number of characters in the destination buffer */
650 dst_chars
= CLIPBOARD_ConvertText(lpSource
->wFormatID
, lpstrS
, src_chars
,
651 lpTarget
->wFormatID
, NULL
, 0);
652 if(!dst_chars
) return NULL
;
654 TRACE("\tconverting from '%s' to '%s', %i chars\n",
655 lpSource
->Name
, lpTarget
->Name
, src_chars
);
657 /* Convert characters to bytes */
658 if(lpTarget
->wFormatID
== CF_UNICODETEXT
)
659 alloc_size
= dst_chars
* sizeof(WCHAR
);
661 alloc_size
= dst_chars
;
663 lpTarget
->hData32
= GlobalAlloc(GMEM_ZEROINIT
| GMEM_MOVEABLE
| GMEM_DDESHARE
, alloc_size
);
664 lpstrT
= (LPSTR
)GlobalLock(lpTarget
->hData32
);
668 CLIPBOARD_ConvertText(lpSource
->wFormatID
, lpstrS
, src_chars
,
669 lpTarget
->wFormatID
, lpstrT
, dst_chars
);
670 GlobalUnlock(lpTarget
->hData32
);
673 lpTarget
->hData32
= 0;
676 if (lpSource
->hData32
)
677 GlobalUnlock(lpSource
->hData32
);
679 GlobalUnlock16(lpSource
->hData16
);
682 return (lpTarget
->hData16
|| lpTarget
->hData32
) ? lpTarget
: NULL
;
685 /**************************************************************************
686 * CLIPBOARD_EnumClipboardFormats (internal)
688 static UINT
CLIPBOARD_EnumClipboardFormats( UINT wFormat
)
690 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
693 if (wFormat
== 0) /* start from the beginning */
694 lpFormat
= ClipFormats
;
697 /* walk up to the specified format record */
699 if( !(lpFormat
= __lookup_format( lpFormat
, wFormat
)) )
701 lpFormat
= lpFormat
->NextFormat
; /* right */
706 if (lpFormat
== NULL
) return 0;
708 if(CLIPBOARD_IsPresent(lpFormat
->wFormatID
))
711 /* Query the driver if not yet in the cache */
712 if (!USER_Driver
.pIsSelectionOwner())
714 if(lpFormat
->wFormatID
== CF_UNICODETEXT
||
715 lpFormat
->wFormatID
== CF_TEXT
||
716 lpFormat
->wFormatID
== CF_OEMTEXT
)
718 if(USER_Driver
.pIsClipboardFormatAvailable(CF_UNICODETEXT
) ||
719 USER_Driver
.pIsClipboardFormatAvailable(CF_TEXT
) ||
720 USER_Driver
.pIsClipboardFormatAvailable(CF_OEMTEXT
))
721 bFormatPresent
= TRUE
;
723 bFormatPresent
= FALSE
;
726 bFormatPresent
= USER_Driver
.pIsClipboardFormatAvailable(lpFormat
->wFormatID
);
732 lpFormat
= lpFormat
->NextFormat
;
735 TRACE("Next available format %d\n", lpFormat
->wFormatID
);
737 return lpFormat
->wFormatID
;
741 /**************************************************************************
742 * WIN32 Clipboard implementation
743 **************************************************************************/
745 /**************************************************************************
746 * OpenClipboard (USER32.@)
748 * Note: Netscape uses NULL hWnd to open the clipboard.
750 BOOL WINAPI
OpenClipboard( HWND hWnd
)
754 TRACE("(%p)...\n", hWnd
);
758 ClipLock
= GetCurrentThreadId();
760 /* Save current user of the clipboard */
761 hWndClipWindow
= WIN_GetFullHandle( hWnd
);
762 bCBHasChanged
= FALSE
;
767 TRACE(" returning %i\n", bRet
);
772 /**************************************************************************
773 * CloseClipboard (USER.138)
775 BOOL16 WINAPI
CloseClipboard16(void)
777 return CloseClipboard();
781 /**************************************************************************
782 * CloseClipboard (USER32.@)
784 BOOL WINAPI
CloseClipboard(void)
788 if (ClipLock
== GetCurrentThreadId())
792 if (bCBHasChanged
&& hWndViewer
) SendMessageW( hWndViewer
, WM_DRAWCLIPBOARD
, 0, 0 );
799 /**************************************************************************
800 * EmptyClipboard (USER.139)
802 BOOL16 WINAPI
EmptyClipboard16(void)
804 return EmptyClipboard();
808 /**************************************************************************
809 * EmptyClipboard (USER32.@)
810 * Empties and acquires ownership of the clipboard
812 BOOL WINAPI
EmptyClipboard(void)
816 if (ClipLock
!= GetCurrentThreadId())
818 WARN("Clipboard not opened by calling task!\n");
822 /* destroy private objects */
824 if (hWndClipOwner
) SendMessageW( hWndClipOwner
, WM_DESTROYCLIPBOARD
, 0, 0 );
826 /* empty the cache */
827 CLIPBOARD_EmptyCache(TRUE
);
829 /* Assign ownership of the clipboard to the current client */
830 hWndClipOwner
= hWndClipWindow
;
832 /* Save the current task */
833 ClipOwner
= GetCurrentThreadId();
835 /* Tell the driver to acquire the selection */
836 USER_Driver
.pAcquireClipboard();
842 /**************************************************************************
843 * GetClipboardOwner (USER32.@)
844 * FIXME: Can't return the owner if the clipbard is owned by an external app
846 HWND WINAPI
GetClipboardOwner(void)
849 return hWndClipOwner
;
853 /**************************************************************************
854 * SetClipboardData (USER.141)
856 HANDLE16 WINAPI
SetClipboardData16( UINT16 wFormat
, HANDLE16 hData
)
858 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
860 TRACE("(%04X, %04x) !\n", wFormat
, hData
);
862 /* NOTE: If the hData is zero and current owner doesn't match
863 * the window that opened the clipboard then this application
864 * is screwed because WM_RENDERFORMAT will go to the owner.
865 * (to become the owner it must call EmptyClipboard() before
869 if( CLIPBOARD_IsLocked() || !lpFormat
||
870 (!hData
&& (!hWndClipOwner
|| (hWndClipOwner
!= hWndClipWindow
))) )
872 WARN("Invalid hData or clipboard not opened by calling task!\n");
876 /* Pass on the request to the driver */
877 USER_Driver
.pSetClipboardData(wFormat
);
879 if ( lpFormat
->wDataPresent
|| lpFormat
->hData16
|| lpFormat
->hData32
)
881 CLIPBOARD_DeleteRecord(lpFormat
, TRUE
);
883 /* delete existing CF_UNICODETEXT/CF_TEXT/CF_OEMTEXT aliases */
884 if(wFormat
== CF_UNICODETEXT
)
886 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
887 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
889 else if(wFormat
== CF_TEXT
)
891 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_UNICODETEXT
-1], TRUE
);
892 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
894 else if(wFormat
== CF_OEMTEXT
)
896 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_UNICODETEXT
-1], TRUE
);
897 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
901 bCBHasChanged
= TRUE
;
902 lpFormat
->wDataPresent
= 1;
903 lpFormat
->hData16
= hData
; /* 0 is legal, see WM_RENDERFORMAT */
904 lpFormat
->hData32
= 0;
906 return lpFormat
->hData16
;
910 /**************************************************************************
911 * SetClipboardData (USER32.@)
913 HANDLE WINAPI
SetClipboardData( UINT wFormat
, HANDLE hData
)
915 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
917 TRACE("(%08X, %p) !\n", wFormat
, hData
);
919 /* NOTE: If the hData is zero and current owner doesn't match
920 * the window that opened the clipboard then this application
921 * is screwed because WM_RENDERFORMAT will go to the owner.
922 * (to become the owner it must call EmptyClipboard() before
926 if( CLIPBOARD_IsLocked() || !lpFormat
||
927 (!hData
&& (!hWndClipOwner
|| (hWndClipOwner
!= hWndClipWindow
))) )
929 WARN("Invalid hData or clipboard not opened by calling task!\n");
933 /* Tell the driver to acquire the selection */
934 USER_Driver
.pAcquireClipboard();
936 if ( lpFormat
->wDataPresent
&&
937 (lpFormat
->hData16
|| lpFormat
->hData32
) )
939 CLIPBOARD_DeleteRecord(lpFormat
, TRUE
);
941 /* delete existing CF_UNICODETEXT/CF_TEXT/CF_OEMTEXT aliases */
942 if(wFormat
== CF_UNICODETEXT
)
944 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
945 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
947 else if(wFormat
== CF_TEXT
)
949 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_UNICODETEXT
-1], TRUE
);
950 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
952 else if(wFormat
== CF_OEMTEXT
)
954 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_UNICODETEXT
-1], TRUE
);
955 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
959 bCBHasChanged
= TRUE
;
960 lpFormat
->wDataPresent
= 1;
961 lpFormat
->hDataSrc32
= hData
; /* Save the source handle */
964 * Make a shared duplicate if the memory is not shared
965 * TODO: What should be done for non-memory objects
967 if ( CLIPBOARD_IsMemoryObject(wFormat
) && hData
&& !(GlobalFlags(hData
) & GMEM_DDESHARE
) )
968 lpFormat
->hData32
= CLIPBOARD_GlobalDupMem( hData
);
970 lpFormat
->hData32
= hData
; /* 0 is legal, see WM_RENDERFORMAT */
972 lpFormat
->hData16
= 0;
974 return lpFormat
->hData32
; /* Should we return lpFormat->hDataSrc32 */
978 /**************************************************************************
979 * GetClipboardData (USER.142)
981 HANDLE16 WINAPI
GetClipboardData16( UINT16 wFormat
)
983 LPWINE_CLIPFORMAT lpRender
= ClipFormats
;
985 TRACE("(%04X)\n", wFormat
);
987 if (CLIPBOARD_IsLocked())
989 WARN("Clipboard not opened by calling task!\n");
993 if( wFormat
== CF_UNICODETEXT
|| wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
)
995 lpRender
= CLIPBOARD_RenderText(wFormat
);
996 if ( !lpRender
) return 0;
1000 lpRender
= __lookup_format( ClipFormats
, wFormat
);
1001 if( !lpRender
|| !CLIPBOARD_RenderFormat(lpRender
) ) return 0;
1004 /* Convert between 32 -> 16 bit data, if necessary */
1005 if( lpRender
->hData32
&& !lpRender
->hData16
1006 && CLIPBOARD_IsMemoryObject(wFormat
) )
1009 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
1010 size
= sizeof( METAFILEPICT16
);
1012 size
= GlobalSize(lpRender
->hData32
);
1014 lpRender
->hData16
= GlobalAlloc16(GMEM_ZEROINIT
, size
);
1015 if( !lpRender
->hData16
)
1016 ERR("(%04X) -- not enough memory in 16b heap\n", wFormat
);
1019 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
1021 FIXME("\timplement function CopyMetaFilePict32to16\n");
1022 FIXME("\tin the appropriate file.\n");
1023 #ifdef SOMEONE_IMPLEMENTED_ME
1024 CopyMetaFilePict32to16( GlobalLock16(lpRender
->hData16
),
1025 GlobalLock(lpRender
->hData32
) );
1030 memcpy( GlobalLock16(lpRender
->hData16
),
1031 GlobalLock(lpRender
->hData32
),
1034 GlobalUnlock16(lpRender
->hData16
);
1035 GlobalUnlock(lpRender
->hData32
);
1039 TRACE("\treturning %04x (type %i)\n",
1040 lpRender
->hData16
, lpRender
->wFormatID
);
1041 return lpRender
->hData16
;
1045 /**************************************************************************
1046 * GetClipboardData (USER32.@)
1048 HANDLE WINAPI
GetClipboardData( UINT wFormat
)
1050 LPWINE_CLIPFORMAT lpRender
= ClipFormats
;
1052 TRACE("(%08X)\n", wFormat
);
1054 if (CLIPBOARD_IsLocked())
1056 WARN("Clipboard not opened by calling task!\n");
1060 if( wFormat
== CF_UNICODETEXT
|| wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
)
1062 lpRender
= CLIPBOARD_RenderText(wFormat
);
1063 if ( !lpRender
) return 0;
1067 lpRender
= __lookup_format( ClipFormats
, wFormat
);
1068 if( !lpRender
|| !CLIPBOARD_RenderFormat(lpRender
) ) return 0;
1071 /* Convert between 16 -> 32 bit data, if necessary */
1072 if( lpRender
->hData16
&& !lpRender
->hData32
1073 && CLIPBOARD_IsMemoryObject(wFormat
) )
1076 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
1077 size
= sizeof( METAFILEPICT
);
1079 size
= GlobalSize16(lpRender
->hData16
);
1080 lpRender
->hData32
= GlobalAlloc(GMEM_ZEROINIT
| GMEM_MOVEABLE
| GMEM_DDESHARE
,
1082 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
1084 FIXME("\timplement function CopyMetaFilePict16to32\n");
1085 FIXME("\tin the appropriate file.\n");
1086 #ifdef SOMEONE_IMPLEMENTED_ME
1087 CopyMetaFilePict16to32( GlobalLock16(lpRender
->hData32
),
1088 GlobalLock(lpRender
->hData16
) );
1093 memcpy( GlobalLock(lpRender
->hData32
),
1094 GlobalLock16(lpRender
->hData16
),
1097 GlobalUnlock(lpRender
->hData32
);
1098 GlobalUnlock16(lpRender
->hData16
);
1101 TRACE("\treturning %p (type %i)\n", lpRender
->hData32
, lpRender
->wFormatID
);
1102 return lpRender
->hData32
;
1106 /**************************************************************************
1107 * CountClipboardFormats (USER.143)
1109 INT16 WINAPI
CountClipboardFormats16(void)
1111 return CountClipboardFormats();
1115 /**************************************************************************
1116 * CountClipboardFormats (USER32.@)
1118 INT WINAPI
CountClipboardFormats(void)
1120 INT FormatCount
= 0;
1121 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
1127 if (lpFormat
== NULL
) break;
1129 if( lpFormat
->wFormatID
!= CF_TEXT
) /* Don't count CF_TEXT */
1132 * The format is available if either:
1133 * 1. The data is already in the cache.
1134 * 2. The selection is not owned by us(WINE) and the data is
1135 * available to the clipboard driver.
1137 if ( lpFormat
->wDataPresent
||
1138 ( !USER_Driver
.pIsSelectionOwner()
1139 && USER_Driver
.pIsClipboardFormatAvailable( lpFormat
->wFormatID
) ) )
1141 TRACE("\tdata found for format 0x%04x(%s)\n",
1142 lpFormat
->wFormatID
, CLIPBOARD_GetFormatName(lpFormat
->wFormatID
, NULL
, 0));
1147 lpFormat
= lpFormat
->NextFormat
;
1150 /* these are equivalent, adjust the total */
1151 FormatCount
+= (ClipFormats
[CF_UNICODETEXT
-1].wDataPresent
||
1152 ClipFormats
[CF_TEXT
-1].wDataPresent
||
1153 ClipFormats
[CF_OEMTEXT
-1].wDataPresent
) ? 1 : 0;
1155 TRACE("\ttotal %d\n", FormatCount
);
1159 /**************************************************************************
1160 * EnumClipboardFormats (USER.144)
1162 UINT16 WINAPI
EnumClipboardFormats16( UINT16 wFormat
)
1164 return EnumClipboardFormats( wFormat
);
1168 /**************************************************************************
1169 * EnumClipboardFormats (USER32.@)
1171 UINT WINAPI
EnumClipboardFormats( UINT wFormat
)
1173 TRACE("(%04X)\n", wFormat
);
1175 if (CLIPBOARD_IsLocked())
1177 WARN("Clipboard not opened by calling task!\n");
1181 return CLIPBOARD_EnumClipboardFormats(wFormat
);
1185 /**************************************************************************
1186 * RegisterClipboardFormatA (USER32.@)
1188 UINT WINAPI
RegisterClipboardFormatA( LPCSTR FormatName
)
1190 LPWINE_CLIPFORMAT lpNewFormat
;
1191 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
1193 if (FormatName
== NULL
) return 0;
1195 TRACE("('%s') !\n", FormatName
);
1197 /* walk format chain to see if it's already registered */
1201 if ( !strcasecmp(lpFormat
->Name
,FormatName
) )
1203 lpFormat
->wRefCount
++;
1204 return lpFormat
->wFormatID
;
1207 if ( lpFormat
->NextFormat
== NULL
) break;
1209 lpFormat
= lpFormat
->NextFormat
;
1212 /* allocate storage for new format entry */
1214 lpNewFormat
= (LPWINE_CLIPFORMAT
)HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_CLIPFORMAT
));
1215 if(lpNewFormat
== NULL
) {
1216 WARN("No more memory for a new format!\n");
1219 lpFormat
->NextFormat
= lpNewFormat
;
1220 lpNewFormat
->wRefCount
= 1;
1222 if (!(lpNewFormat
->Name
= HeapAlloc(GetProcessHeap(), 0, strlen(FormatName
)+1 )))
1224 WARN("No more memory for the new format name!\n");
1225 HeapFree(GetProcessHeap(), 0, lpNewFormat
);
1228 strcpy( lpNewFormat
->Name
, FormatName
);
1229 CharLowerA(lpNewFormat
->Name
);
1231 lpNewFormat
->wDataPresent
= 0;
1232 lpNewFormat
->hData16
= 0;
1233 lpNewFormat
->hDataSrc32
= 0;
1234 lpNewFormat
->hData32
= 0;
1235 lpNewFormat
->drvData
= 0;
1236 lpNewFormat
->PrevFormat
= lpFormat
;
1237 lpNewFormat
->NextFormat
= NULL
;
1239 /* Pass on the registration request to the driver */
1240 lpNewFormat
->wFormatID
= USER_Driver
.pRegisterClipboardFormat(lpNewFormat
->Name
);
1242 TRACE("Registering format(%d): %s\n", lpNewFormat
->wFormatID
, FormatName
);
1243 return lpNewFormat
->wFormatID
;
1247 /**************************************************************************
1248 * RegisterClipboardFormat (USER.145)
1250 UINT16 WINAPI
RegisterClipboardFormat16( LPCSTR FormatName
)
1252 return RegisterClipboardFormatA( FormatName
);
1256 /**************************************************************************
1257 * RegisterClipboardFormatW (USER32.@)
1259 UINT WINAPI
RegisterClipboardFormatW( LPCWSTR formatName
)
1261 LPSTR aFormat
= HEAP_strdupWtoA( GetProcessHeap(), 0, formatName
);
1262 UINT ret
= RegisterClipboardFormatA( aFormat
);
1263 HeapFree( GetProcessHeap(), 0, aFormat
);
1268 /**************************************************************************
1269 * GetClipboardFormatName (USER.146)
1271 INT16 WINAPI
GetClipboardFormatName16( UINT16 wFormat
, LPSTR retStr
, INT16 maxlen
)
1273 return GetClipboardFormatNameA( wFormat
, retStr
, maxlen
);
1277 /**************************************************************************
1278 * GetClipboardFormatNameA (USER32.@)
1280 INT WINAPI
GetClipboardFormatNameA( UINT wFormat
, LPSTR retStr
, INT maxlen
)
1282 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
1284 TRACE("(%04X, %p, %d) !\n", wFormat
, retStr
, maxlen
);
1286 if (lpFormat
== NULL
|| lpFormat
->Name
== NULL
)
1288 /* Check if another wine process already registered the format */
1289 if (wFormat
&& !USER_Driver
.pGetClipboardFormatName(wFormat
, retStr
, maxlen
))
1291 RegisterClipboardFormatA(retStr
); /* Make a cache entry */
1292 return strlen(retStr
);
1296 TRACE("wFormat=%d not found\n", wFormat
);
1301 TRACE("Name='%s' !\n", lpFormat
->Name
);
1303 lstrcpynA( retStr
, lpFormat
->Name
, maxlen
);
1304 return strlen(retStr
);
1308 /**************************************************************************
1309 * GetClipboardFormatNameW (USER32.@)
1311 INT WINAPI
GetClipboardFormatNameW( UINT wFormat
, LPWSTR retStr
, INT maxlen
)
1314 LPSTR p
= HeapAlloc( GetProcessHeap(), 0, maxlen
);
1315 if(p
== NULL
) return 0; /* FIXME: is this the correct failure value? */
1317 ret
= GetClipboardFormatNameA( wFormat
, p
, maxlen
);
1319 if (maxlen
> 0 && !MultiByteToWideChar( CP_ACP
, 0, p
, -1, retStr
, maxlen
))
1320 retStr
[maxlen
-1] = 0;
1321 HeapFree( GetProcessHeap(), 0, p
);
1326 /**************************************************************************
1327 * SetClipboardViewer (USER32.@)
1329 HWND WINAPI
SetClipboardViewer( HWND hWnd
)
1331 HWND hwndPrev
= hWndViewer
;
1333 TRACE("(%p): returning %p\n", hWnd
, hwndPrev
);
1335 hWndViewer
= WIN_GetFullHandle( hWnd
);
1340 /**************************************************************************
1341 * GetClipboardViewer (USER32.@)
1343 HWND WINAPI
GetClipboardViewer(void)
1350 /**************************************************************************
1351 * ChangeClipboardChain (USER32.@)
1353 BOOL WINAPI
ChangeClipboardChain(HWND hWnd
, HWND hWndNext
)
1357 FIXME("(%p, %p): stub?\n", hWnd
, hWndNext
);
1360 bRet
= !SendMessageW( hWndViewer
, WM_CHANGECBCHAIN
, (WPARAM
)hWnd
, (LPARAM
)hWndNext
);
1362 WARN("hWndViewer is lost\n");
1364 if( WIN_GetFullHandle(hWnd
) == hWndViewer
) hWndViewer
= WIN_GetFullHandle( hWndNext
);
1370 /**************************************************************************
1371 * IsClipboardFormatAvailable (USER.193)
1373 BOOL16 WINAPI
IsClipboardFormatAvailable16( UINT16 wFormat
)
1375 return IsClipboardFormatAvailable( wFormat
);
1379 /**************************************************************************
1380 * IsClipboardFormatAvailable (USER32.@)
1382 BOOL WINAPI
IsClipboardFormatAvailable( UINT wFormat
)
1386 if (wFormat
== 0) /* Reject this case quickly */
1390 UINT iret
= CLIPBOARD_EnumClipboardFormats(wFormat
- 1);
1391 if ((wFormat
== CF_TEXT
) || (wFormat
== CF_OEMTEXT
) || (wFormat
== CF_UNICODETEXT
))
1392 bRet
= ((iret
== CF_TEXT
) || (iret
== CF_OEMTEXT
) || (iret
== CF_UNICODETEXT
));
1394 bRet
= iret
== wFormat
;
1396 TRACE("(%04X)- ret(%d)\n", wFormat
, bRet
);
1401 /**************************************************************************
1402 * GetOpenClipboardWindow (USER32.@)
1403 * FIXME: This wont work if an external app owns the selection
1405 HWND WINAPI
GetOpenClipboardWindow(void)
1408 return hWndClipWindow
;
1412 /**************************************************************************
1413 * GetPriorityClipboardFormat (USER32.@)
1415 INT WINAPI
GetPriorityClipboardFormat( UINT
*list
, INT nCount
)
1420 if(CountClipboardFormats() == 0) return 0;
1422 for (i
= 0; i
< nCount
; i
++)
1423 if (IsClipboardFormatAvailable( list
[i
] )) return list
[i
];
1428 /**************************************************************************
1429 * GetClipboardSequenceNumber (USER32.@)
1430 * Supported on Win2k/Win98
1431 * MSDN: Windows clipboard code keeps a serial number for the clipboard
1432 * for each window station. The number is incremented whenever the
1433 * contents change or are emptied.
1434 * If you do not have WINSTA_ACCESSCLIPBOARD then the function returns 0
1436 DWORD WINAPI
GetClipboardSequenceNumber(VOID
)
1438 FIXME("Returning 0, see windows/clipboard.c\n");
1439 /* FIXME: Use serial numbers */