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 */