2 * WIN32 clipboard implementation
4 * Copyright 1994 Martin Ayotte
9 * This file contains the implementation for the WIN32 Clipboard API
10 * and Wine's internal clipboard cache.
11 * The actual contents of the clipboard are held in the clipboard cache.
12 * The internal implementation talks to a "clipboard driver" to fill or
13 * expose the cache to the native device. (Currently only the X11 and
14 * TTY clipboard driver are available)
21 #include <sys/types.h>
27 #include "wine/winuser16.h"
28 #include "wine/winbase16.h"
33 #include "clipboard.h"
35 #include "debugtools.h"
37 DEFAULT_DEBUG_CHANNEL(clipboard
)
39 #define CF_REGFORMATBASE 0xC000
41 /**************************************************************************
42 * Clipboard context global variables
45 CLIPBOARD_DRIVER
*CLIPBOARD_Driver
= NULL
;
47 static HANDLE hClipLock
= 0;
48 static BOOL bCBHasChanged
= FALSE
;
50 HWND hWndClipWindow
= 0; /* window that last opened clipboard */
51 HWND hWndClipOwner
= 0; /* current clipboard owner */
52 HANDLE16 hTaskClipOwner
= 0; /* clipboard owner's task */
53 static HWND hWndViewer
= 0; /* start of viewers chain */
55 static WORD LastRegFormat
= CF_REGFORMATBASE
;
57 /* Clipboard cache initial data.
58 * WARNING: This data ordering is dependendent on the WINE_CLIPFORMAT structure
59 * declared in clipboard.h
61 WINE_CLIPFORMAT ClipFormats
[16] = {
62 { CF_TEXT
, 1, 0, "Text", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, NULL
, &ClipFormats
[1]},
63 { CF_BITMAP
, 1, 0, "Bitmap", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, &ClipFormats
[0], &ClipFormats
[2]},
64 { CF_METAFILEPICT
, 1, 0, "MetaFile Picture", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, &ClipFormats
[1], &ClipFormats
[3]},
65 { CF_SYLK
, 1, 0, "Sylk", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, &ClipFormats
[2], &ClipFormats
[4]},
66 { CF_DIF
, 1, 0, "DIF", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, &ClipFormats
[3], &ClipFormats
[5]},
67 { CF_TIFF
, 1, 0, "TIFF", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, &ClipFormats
[4], &ClipFormats
[6]},
68 { CF_OEMTEXT
, 1, 0, "OEM Text", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, &ClipFormats
[5], &ClipFormats
[7]},
69 { CF_DIB
, 1, 0, "DIB", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, &ClipFormats
[6], &ClipFormats
[8]},
70 { CF_PALETTE
, 1, 0, "Palette", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, &ClipFormats
[7], &ClipFormats
[9]},
71 { CF_PENDATA
, 1, 0, "PenData", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, &ClipFormats
[8], &ClipFormats
[10]},
72 { CF_RIFF
, 1, 0, "RIFF", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, &ClipFormats
[9], &ClipFormats
[11]},
73 { CF_WAVE
, 1, 0, "Wave", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, &ClipFormats
[10], &ClipFormats
[12]},
74 { CF_OWNERDISPLAY
, 1, 0, "Owner Display", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, &ClipFormats
[11], &ClipFormats
[13]},
75 { CF_DSPTEXT
, 1, 0, "DSPText", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, &ClipFormats
[12], &ClipFormats
[14]},
76 { CF_DSPMETAFILEPICT
, 1, 0, "DSPMetaFile Picture", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, &ClipFormats
[13], &ClipFormats
[15]},
77 { CF_DSPBITMAP
, 1, 0, "DSPBitmap", (HANDLE16
)NULL
, (HANDLE
)NULL
, (HANDLE
)NULL
, 0, &ClipFormats
[14], NULL
}
81 /**************************************************************************
82 * Internal Clipboard implementation methods
83 **************************************************************************/
86 /**************************************************************************
87 * CLIPBOARD_LookupFormat
89 static LPWINE_CLIPFORMAT
__lookup_format( LPWINE_CLIPFORMAT lpFormat
, WORD wID
)
93 if (lpFormat
== NULL
||
94 lpFormat
->wFormatID
== wID
) break;
95 lpFormat
= lpFormat
->NextFormat
;
100 LPWINE_CLIPFORMAT
CLIPBOARD_LookupFormat( WORD wID
)
102 return __lookup_format( ClipFormats
, wID
);
105 /**************************************************************************
107 * Check if the clipboard cache is available to the caller
109 BOOL
CLIPBOARD_IsLocked()
111 BOOL bIsLocked
= TRUE
;
112 HANDLE16 hTaskCur
= GetCurrentTask();
115 * The clipboard is available:
116 * 1. if the caller's task has opened the clipboard,
118 * 2. if the caller is the clipboard owners task, AND is responding to a
119 * WM_RENDERFORMAT message.
121 if ( hClipLock
== hTaskCur
)
124 else if ( hTaskCur
== hTaskClipOwner
)
126 /* Check if we're currently executing inside a window procedure
127 * called in response to a WM_RENDERFORMAT message. A WM_RENDERFORMAT
128 * handler is not permitted to open the clipboard since it has been opened
129 * by another client. However the handler must have access to the
130 * clipboard in order to update data in response to this message.
132 MESSAGEQUEUE
*queue
= QUEUE_Lock( GetFastQueue16() );
136 && queue
->smWaiting
->msg
== WM_RENDERFORMAT
137 && queue
->smWaiting
->hSrcQueue
141 QUEUE_Unlock( queue
);
147 /**************************************************************************
148 * CLIPBOARD_ReleaseOwner
149 * Gives up ownership of the clipboard
151 void CLIPBOARD_ReleaseOwner()
157 /**************************************************************************
158 * CLIPBOARD_GlobalFreeProc
160 * This is a callback mechanism to allow HGLOBAL data to be released in
161 * the context of the process which allocated it. We post a WM_TIMER message
162 * to the owner window(in CLIPBOARD_DeleteRecord) and destroy the data(in idEvent)
163 * in this WndProc, which is invoked when the apps message loop calls DispatchMessage.
164 * This technique is discussed in Matt Pietrek's "Under the Hood".
165 * An article describing the same may be found in MSDN by searching for WM_TIMER.
166 * Note that this mechanism will probably stop working when WINE supports
167 * address space separation. When "queue events" are implemented in Wine we
168 * should switch to using that mechanism, since it is more robust and does not
169 * require a procedure address to be passed. See the SetWinEventHook API for
172 VOID CALLBACK
CLIPBOARD_GlobalFreeProc( HWND hwnd
, UINT uMsg
, UINT idEvent
, DWORD dwTime
)
174 /* idEvent is the HGLOBAL to be deleted */
175 GlobalFree( (HGLOBAL
)idEvent
);
178 /**************************************************************************
179 * CLIPBOARD_DeleteRecord
181 void CLIPBOARD_DeleteRecord(LPWINE_CLIPFORMAT lpFormat
, BOOL bChange
)
183 if( (lpFormat
->wFormatID
>= CF_GDIOBJFIRST
&&
184 lpFormat
->wFormatID
<= CF_GDIOBJLAST
) || lpFormat
->wFormatID
== CF_BITMAP
)
186 if (lpFormat
->hData32
)
187 DeleteObject(lpFormat
->hData32
);
188 if (lpFormat
->hData16
)
189 DeleteObject16(lpFormat
->hData16
);
191 else if( lpFormat
->wFormatID
== CF_METAFILEPICT
)
193 if (lpFormat
->hData32
)
195 DeleteMetaFile( ((METAFILEPICT
*)GlobalLock( lpFormat
->hData32
))->hMF
);
196 PostMessageA(hWndClipOwner
, WM_TIMER
,
197 (WPARAM
)lpFormat
->hData32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
198 if (lpFormat
->hDataSrc32
)
200 /* Release lpFormat->hData32 in the context of the process which created it.
201 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
202 * GlobalFree(lpFormat->hDataSrc32);
204 PostMessageA(hWndClipOwner
, WM_TIMER
,
205 (WPARAM
)lpFormat
->hDataSrc32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
208 if (lpFormat
->hData16
)
209 /* HMETAFILE16 and HMETAFILE32 are apparently the same thing,
210 and a shallow copy is enough to share a METAFILEPICT
211 structure between 16bit and 32bit clipboards. The MetaFile
212 should of course only be deleted once. */
213 GlobalFree16(lpFormat
->hData16
);
215 if (lpFormat
->hData16
)
217 DeleteMetaFile16( ((METAFILEPICT16
*)GlobalLock16( lpFormat
->hData16
))->hMF
);
218 GlobalFree16(lpFormat
->hData16
);
223 if (lpFormat
->hData32
)
225 /* Release lpFormat->hData32 in the context of the process which created it.
226 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
227 * GlobalFree( lpFormat->hData32 );
229 PostMessageA(hWndClipOwner
, WM_TIMER
,
230 (WPARAM
)lpFormat
->hData32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
232 if (lpFormat
->hDataSrc32
)
234 /* Release lpFormat->hData32 in the context of the process which created it.
235 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
236 * GlobalFree(lpFormat->hDataSrc32);
238 PostMessageA(hWndClipOwner
, WM_TIMER
,
239 (WPARAM
)lpFormat
->hDataSrc32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
241 if (lpFormat
->hData16
)
242 GlobalFree16(lpFormat
->hData16
);
245 lpFormat
->wDataPresent
= 0;
246 lpFormat
->hData16
= 0;
247 lpFormat
->hData32
= 0;
248 lpFormat
->hDataSrc32
= 0;
249 lpFormat
->drvData
= 0;
251 if( bChange
) bCBHasChanged
= TRUE
;
254 /**************************************************************************
255 * CLIPBOARD_EmptyCache
257 void CLIPBOARD_EmptyCache( BOOL bChange
)
259 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
263 if ( lpFormat
->wDataPresent
|| lpFormat
->hData16
|| lpFormat
->hData32
)
264 CLIPBOARD_DeleteRecord( lpFormat
, bChange
);
266 lpFormat
= lpFormat
->NextFormat
;
270 /**************************************************************************
271 * CLIPBOARD_IsPresent
273 BOOL
CLIPBOARD_IsPresent(WORD wFormat
)
277 if( wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
)
278 return ClipFormats
[CF_TEXT
-1].wDataPresent
||
279 ClipFormats
[CF_OEMTEXT
-1].wDataPresent
;
282 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
283 if( lpFormat
) return (lpFormat
->wDataPresent
);
288 /**************************************************************************
289 * CLIPBOARD_IsCacheRendered
290 * Checks if any data needs to be rendered to the clipboard cache
292 * TRUE - All clipboard data is available in the cache
293 * FALSE - Some data is marked for delayed render and needs rendering
295 BOOL
CLIPBOARD_IsCacheRendered()
297 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
299 /* check if all formats were rendered */
302 if( lpFormat
->wDataPresent
&& !lpFormat
->hData16
&& !lpFormat
->hData32
)
305 lpFormat
= lpFormat
->NextFormat
;
312 /**************************************************************************
313 * CLIPBOARD_IsMemoryObject
314 * Tests if the clipboard format specifies a memory object
316 BOOL
CLIPBOARD_IsMemoryObject( WORD wFormat
)
321 case CF_METAFILEPICT
:
333 /***********************************************************************
334 * CLIPBOARD_GlobalDupMem( HGLOBAL )
335 * Helper method to duplicate an HGLOBAL chunk of memory into shared memory
337 HGLOBAL
CLIPBOARD_GlobalDupMem( HGLOBAL hGlobalSrc
)
340 PVOID pGlobalSrc
, pGlobalDest
;
346 cBytes
= GlobalSize(hGlobalSrc
);
350 /* Turn on the DDESHARE and _MOVEABLE flags explicitly */
351 hGlobalDest
= GlobalAlloc( GlobalFlags(hGlobalSrc
) | GMEM_DDESHARE
| GMEM_MOVEABLE
,
356 pGlobalSrc
= GlobalLock(hGlobalSrc
);
357 pGlobalDest
= GlobalLock(hGlobalDest
);
358 if ( !pGlobalSrc
|| !pGlobalDest
)
361 memcpy(pGlobalDest
, pGlobalSrc
, cBytes
);
363 GlobalUnlock(hGlobalSrc
);
364 GlobalUnlock(hGlobalDest
);
369 /**************************************************************************
370 * CLIPBOARD_GetFormatName
371 * Gets the format name associated with an ID
373 char * CLIPBOARD_GetFormatName(UINT wFormat
)
375 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
376 return (lpFormat
) ? lpFormat
->Name
: NULL
;
380 /**************************************************************************
381 * CLIPBOARD_RenderFormat
383 static BOOL
CLIPBOARD_RenderFormat(LPWINE_CLIPFORMAT lpFormat
)
386 * If WINE is not the selection owner, and the format is available
387 * we must ask the the driver to render the data to the clipboard cache.
389 if ( !CLIPBOARD_Driver
->pIsSelectionOwner()
390 && CLIPBOARD_Driver
->pIsFormatAvailable( lpFormat
->wFormatID
) )
392 if ( !CLIPBOARD_Driver
->pGetData( lpFormat
->wFormatID
) )
396 * If Wine owns the clipboard, and the data is marked for delayed render,
399 else if( lpFormat
->wDataPresent
&& !lpFormat
->hData16
&& !lpFormat
->hData32
)
401 if( IsWindow(hWndClipOwner
) )
403 /* Send a WM_RENDERFORMAT message to notify the owner to render the
404 * data requested into the clipboard.
406 TRACE("Sending WM_RENDERFORMAT message\n");
407 SendMessage16(hWndClipOwner
,WM_RENDERFORMAT
,
408 (WPARAM16
)lpFormat
->wFormatID
,0L);
412 WARN("\thWndClipOwner (%04x) is lost!\n",
414 CLIPBOARD_ReleaseOwner();
415 lpFormat
->wDataPresent
= 0;
420 return (lpFormat
->hData16
|| lpFormat
->hData32
) ? TRUE
: FALSE
;
424 /**************************************************************************
425 * CLIPBOARD_RenderText
427 * Renders text to the clipboard buffer converting between UNIX and DOS formats.
429 * RETURNS: pointer to the WINE_CLIPFORMAT if successful, NULL otherwise
431 * FIXME: Should be a pair of driver functions that convert between OEM text and Windows.
434 static LPWINE_CLIPFORMAT
CLIPBOARD_RenderText( UINT wFormat
)
436 LPWINE_CLIPFORMAT lpSource
= ClipFormats
;
437 LPWINE_CLIPFORMAT lpTarget
;
439 /* Asked for CF_TEXT and not available - always attempt to convert from CF_OEM_TEXT */
440 if( wFormat
== CF_TEXT
&& !ClipFormats
[CF_TEXT
-1].wDataPresent
)
442 /* Convert OEMTEXT -> TEXT */
443 lpSource
= &ClipFormats
[CF_OEMTEXT
-1];
444 lpTarget
= &ClipFormats
[CF_TEXT
-1];
446 TRACE("\tOEMTEXT -> TEXT\n");
448 /* Asked for CF_OEM_TEXT, and CF_TEXT available */
449 else if( wFormat
== CF_OEMTEXT
&& !ClipFormats
[CF_OEMTEXT
-1].wDataPresent
450 && ClipFormats
[CF_TEXT
-1].wDataPresent
)
452 /* Convert TEXT -> OEMTEXT */
453 lpSource
= &ClipFormats
[CF_TEXT
-1];
454 lpTarget
= &ClipFormats
[CF_OEMTEXT
-1];
456 TRACE("\tTEXT -> OEMTEXT\n");
458 /* Text format requested is available - no conversion necessary */
461 lpSource
= __lookup_format( ClipFormats
, wFormat
);
465 /* First render the source text format */
466 if ( !lpSource
|| !CLIPBOARD_RenderFormat(lpSource
) ) return NULL
;
468 /* Convert to the desired target text format, if necessary */
469 if( lpTarget
!= lpSource
&& !lpTarget
->hData16
&& !lpTarget
->hData32
)
475 if (lpSource
->hData32
)
477 size
= GlobalSize( lpSource
->hData32
);
478 lpstrS
= (LPSTR
)GlobalLock(lpSource
->hData32
);
482 size
= GlobalSize16( lpSource
->hData16
);
483 lpstrS
= (LPSTR
)GlobalLock16(lpSource
->hData16
);
486 if( !lpstrS
) return NULL
;
487 TRACE("\tconverting from '%s' to '%s', %i chars\n",
488 lpSource
->Name
, lpTarget
->Name
, size
);
490 lpTarget
->hData32
= GlobalAlloc(GMEM_ZEROINIT
, size
);
491 lpstrT
= (LPSTR
)GlobalLock(lpTarget
->hData32
);
495 if( lpSource
->wFormatID
== CF_TEXT
)
496 CharToOemBuffA(lpstrS
, lpstrT
, size
);
498 OemToCharBuffA(lpstrS
, lpstrT
, size
);
499 TRACE("\tgot %s\n", lpstrT
);
500 GlobalUnlock(lpTarget
->hData32
);
503 lpTarget
->hData32
= 0;
506 if (lpSource
->hData32
)
507 GlobalUnlock(lpSource
->hData32
);
509 GlobalUnlock16(lpSource
->hData16
);
512 return (lpTarget
->hData16
|| lpTarget
->hData32
) ? lpTarget
: NULL
;
515 /**************************************************************************
516 * WIN32 Clipboard implementation
517 **************************************************************************/
519 /**************************************************************************
520 * OpenClipboard16 (USER.137)
522 BOOL16 WINAPI
OpenClipboard16( HWND16 hWnd
)
524 return OpenClipboard( hWnd
);
528 /**************************************************************************
529 * OpenClipboard32 (USER32.407)
531 * Note: Netscape uses NULL hWnd to open the clipboard.
533 BOOL WINAPI
OpenClipboard( HWND hWnd
)
537 TRACE("(%04x)...\n", hWnd
);
541 hClipLock
= GetCurrentTask();
543 /* Save current user of the clipboard */
544 hWndClipWindow
= hWnd
;
545 bCBHasChanged
= FALSE
;
550 TRACE(" returning %i\n", bRet
);
555 /**************************************************************************
556 * CloseClipboard16 (USER.138)
558 BOOL16 WINAPI
CloseClipboard16(void)
560 return CloseClipboard();
564 /**************************************************************************
565 * CloseClipboard32 (USER32.54)
567 BOOL WINAPI
CloseClipboard(void)
571 if (hClipLock
== GetCurrentTask())
575 if (bCBHasChanged
&& hWndViewer
)
576 SendMessage16(hWndViewer
, WM_DRAWCLIPBOARD
, 0, 0L);
583 /**************************************************************************
584 * EmptyClipboard16 (USER.139)
586 BOOL16 WINAPI
EmptyClipboard16(void)
588 return EmptyClipboard();
592 /**************************************************************************
593 * EmptyClipboard32 (USER32.169)
594 * Empties and acquires ownership of the clipboard
596 BOOL WINAPI
EmptyClipboard(void)
600 if (hClipLock
!= GetCurrentTask())
602 WARN("Clipboard not opened by calling task!");
606 /* destroy private objects */
609 SendMessage16(hWndClipOwner
, WM_DESTROYCLIPBOARD
, 0, 0L);
611 /* empty the cache */
612 CLIPBOARD_EmptyCache(TRUE
);
614 /* Assign ownership of the clipboard to the current client */
615 hWndClipOwner
= hWndClipWindow
;
617 /* Save the current task */
618 hTaskClipOwner
= GetCurrentTask();
620 /* Tell the driver to acquire the selection */
621 CLIPBOARD_Driver
->pAcquire();
627 /**************************************************************************
628 * GetClipboardOwner16 (USER.140)
629 * FIXME: Can't return the owner if the clipbard is owned by an external app
631 HWND16 WINAPI
GetClipboardOwner16(void)
634 return hWndClipOwner
;
638 /**************************************************************************
639 * GetClipboardOwner32 (USER32.225)
640 * FIXME: Can't return the owner if the clipbard is owned by an external app
642 HWND WINAPI
GetClipboardOwner(void)
645 return hWndClipOwner
;
649 /**************************************************************************
650 * SetClipboardData16 (USER.141)
652 HANDLE16 WINAPI
SetClipboardData16( UINT16 wFormat
, HANDLE16 hData
)
654 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
656 TRACE("(%04X, %04x) !\n", wFormat
, hData
);
658 /* NOTE: If the hData is zero and current owner doesn't match
659 * the window that opened the clipboard then this application
660 * is screwed because WM_RENDERFORMAT will go to the owner.
661 * (to become the owner it must call EmptyClipboard() before
665 if( CLIPBOARD_IsLocked() || !lpFormat
||
666 (!hData
&& (!hWndClipOwner
|| (hWndClipOwner
!= hWndClipWindow
))) )
668 WARN("Invalid hData or clipboard not opened by calling task!");
672 /* Pass on the request to the driver */
673 CLIPBOARD_Driver
->pSetData(wFormat
);
675 if ( lpFormat
->wDataPresent
|| lpFormat
->hData16
|| lpFormat
->hData32
)
677 CLIPBOARD_DeleteRecord(lpFormat
, TRUE
);
679 /* delete existing CF_TEXT/CF_OEMTEXT aliases */
681 if( wFormat
== CF_TEXT
682 && ( ClipFormats
[CF_OEMTEXT
-1].hData16
683 || ClipFormats
[CF_OEMTEXT
-1].hData32
)
684 && !ClipFormats
[CF_OEMTEXT
-1].wDataPresent
)
685 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
686 if( wFormat
== CF_OEMTEXT
687 && ( ClipFormats
[CF_OEMTEXT
-1].hData16
688 || ClipFormats
[CF_OEMTEXT
-1].hData32
)
689 && !ClipFormats
[CF_TEXT
-1].wDataPresent
)
690 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
693 bCBHasChanged
= TRUE
;
694 lpFormat
->wDataPresent
= 1;
695 lpFormat
->hData16
= hData
; /* 0 is legal, see WM_RENDERFORMAT */
696 lpFormat
->hData32
= 0;
698 return lpFormat
->hData16
;
702 /**************************************************************************
703 * SetClipboardData (USER32.470)
705 HANDLE WINAPI
SetClipboardData( UINT wFormat
, HANDLE hData
)
707 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
709 TRACE("(%08X, %08x) !\n", wFormat
, hData
);
711 /* NOTE: If the hData is zero and current owner doesn't match
712 * the window that opened the clipboard then this application
713 * is screwed because WM_RENDERFORMAT will go to the owner.
714 * (to become the owner it must call EmptyClipboard() before
718 if( CLIPBOARD_IsLocked() || !lpFormat
||
719 (!hData
&& (!hWndClipOwner
|| (hWndClipOwner
!= hWndClipWindow
))) )
721 WARN("Invalid hData or clipboard not opened by calling task!");
725 /* Tell the driver to acquire the selection */
726 CLIPBOARD_Driver
->pAcquire();
728 if ( lpFormat
->wDataPresent
&&
729 (lpFormat
->hData16
|| lpFormat
->hData32
) )
731 CLIPBOARD_DeleteRecord(lpFormat
, TRUE
);
733 /* delete existing CF_TEXT/CF_OEMTEXT aliases */
735 if( wFormat
== CF_TEXT
736 && ( ClipFormats
[CF_OEMTEXT
-1].hData16
737 || ClipFormats
[CF_OEMTEXT
-1].hData32
)
738 && !ClipFormats
[CF_OEMTEXT
-1].wDataPresent
)
739 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
740 if( wFormat
== CF_OEMTEXT
741 && ( ClipFormats
[CF_OEMTEXT
-1].hData16
742 || ClipFormats
[CF_OEMTEXT
-1].hData32
)
743 && !ClipFormats
[CF_TEXT
-1].wDataPresent
)
744 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
747 bCBHasChanged
= TRUE
;
748 lpFormat
->wDataPresent
= 1;
749 lpFormat
->hDataSrc32
= hData
; /* Save the source handle */
752 * Make a shared duplicate if the memory is not shared
753 * TODO: What should be done for non-memory objects
755 if ( CLIPBOARD_IsMemoryObject(wFormat
) && hData
&& !(GlobalFlags(hData
) & GMEM_DDESHARE
) )
756 lpFormat
->hData32
= CLIPBOARD_GlobalDupMem( hData
);
758 lpFormat
->hData32
= hData
; /* 0 is legal, see WM_RENDERFORMAT */
760 lpFormat
->hData16
= 0;
762 return lpFormat
->hData32
; /* Should we return lpFormat->hDataSrc32 */
766 /**************************************************************************
767 * GetClipboardData16 (USER.142)
769 HANDLE16 WINAPI
GetClipboardData16( UINT16 wFormat
)
771 LPWINE_CLIPFORMAT lpRender
= ClipFormats
;
773 TRACE("(%04X)\n", wFormat
);
775 if (CLIPBOARD_IsLocked())
777 WARN("Clipboard not opened by calling task!");
781 if( wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
)
783 lpRender
= CLIPBOARD_RenderText(wFormat
);
784 if ( !lpRender
) return 0;
788 lpRender
= __lookup_format( ClipFormats
, wFormat
);
789 if( !lpRender
|| !CLIPBOARD_RenderFormat(lpRender
) ) return 0;
792 /* Convert between 32 -> 16 bit data, if necessary */
793 if( lpRender
->hData32
&& !lpRender
->hData16
)
796 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
797 size
= sizeof( METAFILEPICT16
);
799 size
= GlobalSize(lpRender
->hData32
);
801 lpRender
->hData16
= GlobalAlloc16(GMEM_ZEROINIT
, size
);
802 if( !lpRender
->hData16
)
803 ERR("(%04X) -- not enough memory in 16b heap\n", wFormat
);
806 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
808 FIXME("\timplement function CopyMetaFilePict32to16\n");
809 FIXME("\tin the appropriate file.\n");
810 #ifdef SOMEONE_IMPLEMENTED_ME
811 CopyMetaFilePict32to16( GlobalLock16(lpRender
->hData16
),
812 GlobalLock(lpRender
->hData32
) );
817 memcpy( GlobalLock16(lpRender
->hData16
),
818 GlobalLock(lpRender
->hData32
),
821 GlobalUnlock16(lpRender
->hData16
);
822 GlobalUnlock(lpRender
->hData32
);
826 TRACE("\treturning %04x (type %i)\n",
827 lpRender
->hData16
, lpRender
->wFormatID
);
828 return lpRender
->hData16
;
832 /**************************************************************************
833 * GetClipboardData32 (USER32.222)
835 HANDLE WINAPI
GetClipboardData( UINT wFormat
)
837 LPWINE_CLIPFORMAT lpRender
= ClipFormats
;
839 TRACE("(%08X)\n", wFormat
);
841 if (CLIPBOARD_IsLocked())
843 WARN("Clipboard not opened by calling task!");
847 if( wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
)
849 lpRender
= CLIPBOARD_RenderText(wFormat
);
850 if ( !lpRender
) return 0;
854 lpRender
= __lookup_format( ClipFormats
, wFormat
);
855 if( !lpRender
|| !CLIPBOARD_RenderFormat(lpRender
) ) return 0;
858 /* Convert between 16 -> 32 bit data, if necessary */
859 if( lpRender
->hData16
&& !lpRender
->hData32
)
862 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
863 size
= sizeof( METAFILEPICT
);
865 size
= GlobalSize16(lpRender
->hData16
);
866 lpRender
->hData32
= GlobalAlloc(GMEM_ZEROINIT
| GMEM_MOVEABLE
| GMEM_DDESHARE
,
868 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
870 FIXME("\timplement function CopyMetaFilePict16to32\n");
871 FIXME("\tin the appropriate file.\n");
872 #ifdef SOMEONE_IMPLEMENTED_ME
873 CopyMetaFilePict16to32( GlobalLock16(lpRender
->hData32
),
874 GlobalLock(lpRender
->hData16
) );
879 memcpy( GlobalLock(lpRender
->hData32
),
880 GlobalLock16(lpRender
->hData16
),
883 GlobalUnlock(lpRender
->hData32
);
884 GlobalUnlock16(lpRender
->hData16
);
887 TRACE("\treturning %04x (type %i)\n",
888 lpRender
->hData32
, lpRender
->wFormatID
);
889 return lpRender
->hData32
;
893 /**************************************************************************
894 * CountClipboardFormats16 (USER.143)
896 INT16 WINAPI
CountClipboardFormats16(void)
898 return CountClipboardFormats();
902 /**************************************************************************
903 * CountClipboardFormats32 (USER32.63)
905 INT WINAPI
CountClipboardFormats(void)
908 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
914 if (lpFormat
== NULL
) break;
916 if( lpFormat
->wFormatID
!= CF_TEXT
) /* Don't count CF_TEXT */
919 * The format is available if either:
920 * 1. The data is already in the cache.
921 * 2. The selection is not owned by us(WINE) and the data is
922 * available to the clipboard driver.
924 if ( lpFormat
->wDataPresent
||
925 ( !CLIPBOARD_Driver
->pIsSelectionOwner()
926 && CLIPBOARD_Driver
->pIsFormatAvailable( lpFormat
->wFormatID
) ) )
928 TRACE("\tdata found for format %i(%s)\n",
929 lpFormat
->wFormatID
, CLIPBOARD_GetFormatName(lpFormat
->wFormatID
));
934 lpFormat
= lpFormat
->NextFormat
;
937 /* these two are equivalent, adjust the total */
939 FormatCount
+= abs(ClipFormats
[CF_TEXT
-1].wDataPresent
-
940 ClipFormats
[CF_OEMTEXT
-1].wDataPresent
);
942 TRACE("\ttotal %d\n", FormatCount
);
947 /**************************************************************************
948 * EnumClipboardFormats16 (USER.144)
950 UINT16 WINAPI
EnumClipboardFormats16( UINT16 wFormat
)
952 return EnumClipboardFormats( wFormat
);
956 /**************************************************************************
957 * EnumClipboardFormats32 (USER32.179)
959 UINT WINAPI
EnumClipboardFormats( UINT wFormat
)
961 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
964 TRACE("(%04X)\n", wFormat
);
966 if (CLIPBOARD_IsLocked())
968 WARN("Clipboard not opened by calling task!");
972 if (wFormat
== 0) /* start from the beginning */
973 lpFormat
= ClipFormats
;
976 /* walk up to the specified format record */
978 if( !(lpFormat
= __lookup_format( lpFormat
, wFormat
)) )
980 lpFormat
= lpFormat
->NextFormat
; /* right */
985 if (lpFormat
== NULL
) return 0;
987 /* Synthesize CF_TEXT from CF_OEMTEXT and vice versa */
988 bFormatPresent
= (lpFormat
->wDataPresent
||
989 (lpFormat
->wFormatID
== CF_OEMTEXT
&& ClipFormats
[CF_TEXT
-1].wDataPresent
) ||
990 (lpFormat
->wFormatID
== CF_TEXT
&& ClipFormats
[CF_OEMTEXT
-1].wDataPresent
) );
992 /* Query the driver if not yet in the cache */
993 if (!bFormatPresent
&& !CLIPBOARD_Driver
->pIsSelectionOwner())
996 CLIPBOARD_Driver
->pIsFormatAvailable( (lpFormat
->wFormatID
== CF_TEXT
) ?
997 CF_OEMTEXT
: lpFormat
->wFormatID
);
1003 lpFormat
= lpFormat
->NextFormat
;
1006 return lpFormat
->wFormatID
;
1010 /**************************************************************************
1011 * RegisterClipboardFormat16 (USER.145)
1013 UINT16 WINAPI
RegisterClipboardFormat16( LPCSTR FormatName
)
1015 LPWINE_CLIPFORMAT lpNewFormat
;
1016 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
1018 if (FormatName
== NULL
) return 0;
1020 TRACE("('%s') !\n", FormatName
);
1022 /* walk format chain to see if it's already registered */
1026 if ( !strcmp(lpFormat
->Name
,FormatName
) )
1028 lpFormat
->wRefCount
++;
1029 return lpFormat
->wFormatID
;
1032 if ( lpFormat
->NextFormat
== NULL
) break;
1034 lpFormat
= lpFormat
->NextFormat
;
1037 /* allocate storage for new format entry */
1039 lpNewFormat
= (LPWINE_CLIPFORMAT
)xmalloc(sizeof(WINE_CLIPFORMAT
));
1040 lpFormat
->NextFormat
= lpNewFormat
;
1041 lpNewFormat
->wFormatID
= LastRegFormat
;
1042 lpNewFormat
->wRefCount
= 1;
1044 lpNewFormat
->Name
= (LPSTR
)xmalloc(strlen(FormatName
) + 1);
1045 strcpy(lpNewFormat
->Name
, FormatName
);
1047 lpNewFormat
->wDataPresent
= 0;
1048 lpNewFormat
->hData16
= 0;
1049 lpNewFormat
->hDataSrc32
= 0;
1050 lpNewFormat
->hData32
= 0;
1051 lpNewFormat
->drvData
= 0;
1052 lpNewFormat
->PrevFormat
= lpFormat
;
1053 lpNewFormat
->NextFormat
= NULL
;
1055 /* Pass on the registration request to the driver */
1056 CLIPBOARD_Driver
->pRegisterFormat( FormatName
);
1058 return LastRegFormat
++;
1062 /**************************************************************************
1063 * RegisterClipboardFormat32A (USER32.431)
1065 UINT WINAPI
RegisterClipboardFormatA( LPCSTR formatName
)
1067 return RegisterClipboardFormat16( formatName
);
1071 /**************************************************************************
1072 * RegisterClipboardFormat32W (USER32.432)
1074 UINT WINAPI
RegisterClipboardFormatW( LPCWSTR formatName
)
1076 LPSTR aFormat
= HEAP_strdupWtoA( GetProcessHeap(), 0, formatName
);
1077 UINT ret
= RegisterClipboardFormatA( aFormat
);
1078 HeapFree( GetProcessHeap(), 0, aFormat
);
1083 /**************************************************************************
1084 * GetClipboardFormatName16 (USER.146)
1086 INT16 WINAPI
GetClipboardFormatName16( UINT16 wFormat
, LPSTR retStr
, INT16 maxlen
)
1088 return GetClipboardFormatNameA( wFormat
, retStr
, maxlen
);
1092 /**************************************************************************
1093 * GetClipboardFormatName32A (USER32.223)
1095 INT WINAPI
GetClipboardFormatNameA( UINT wFormat
, LPSTR retStr
, INT maxlen
)
1097 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
1099 TRACE("(%04X, %p, %d) !\n", wFormat
, retStr
, maxlen
);
1101 if (lpFormat
== NULL
|| lpFormat
->Name
== NULL
||
1102 lpFormat
->wFormatID
< CF_REGFORMATBASE
) return 0;
1104 TRACE("Name='%s' !\n", lpFormat
->Name
);
1106 lstrcpynA( retStr
, lpFormat
->Name
, maxlen
);
1107 return strlen(retStr
);
1111 /**************************************************************************
1112 * GetClipboardFormatName32W (USER32.224)
1114 INT WINAPI
GetClipboardFormatNameW( UINT wFormat
, LPWSTR retStr
, INT maxlen
)
1116 LPSTR p
= HEAP_xalloc( GetProcessHeap(), 0, maxlen
);
1117 INT ret
= GetClipboardFormatNameA( wFormat
, p
, maxlen
);
1118 lstrcpynAtoW( retStr
, p
, maxlen
);
1119 HeapFree( GetProcessHeap(), 0, p
);
1124 /**************************************************************************
1125 * SetClipboardViewer16 (USER.147)
1127 HWND16 WINAPI
SetClipboardViewer16( HWND16 hWnd
)
1129 TRACE("(%04x)\n", hWnd
);
1130 return SetClipboardViewer( hWnd
);
1134 /**************************************************************************
1135 * SetClipboardViewer32 (USER32.471)
1137 HWND WINAPI
SetClipboardViewer( HWND hWnd
)
1139 HWND hwndPrev
= hWndViewer
;
1141 TRACE("(%04x): returning %04x\n", hWnd
, hwndPrev
);
1148 /**************************************************************************
1149 * GetClipboardViewer16 (USER.148)
1151 HWND16 WINAPI
GetClipboardViewer16(void)
1158 /**************************************************************************
1159 * GetClipboardViewer32 (USER32.226)
1161 HWND WINAPI
GetClipboardViewer(void)
1168 /**************************************************************************
1169 * ChangeClipboardChain16 (USER.149)
1171 BOOL16 WINAPI
ChangeClipboardChain16(HWND16 hWnd
, HWND16 hWndNext
)
1173 return ChangeClipboardChain(hWnd
, hWndNext
);
1177 /**************************************************************************
1178 * ChangeClipboardChain32 (USER32.22)
1180 BOOL WINAPI
ChangeClipboardChain(HWND hWnd
, HWND hWndNext
)
1184 FIXME("(0x%04x, 0x%04x): stub?\n", hWnd
, hWndNext
);
1187 bRet
= !SendMessage16( hWndViewer
, WM_CHANGECBCHAIN
,
1188 (WPARAM16
)hWnd
, (LPARAM
)hWndNext
);
1190 WARN("hWndViewer is lost\n");
1192 if( hWnd
== hWndViewer
) hWndViewer
= hWndNext
;
1198 /**************************************************************************
1199 * IsClipboardFormatAvailable16 (USER.193)
1201 BOOL16 WINAPI
IsClipboardFormatAvailable16( UINT16 wFormat
)
1203 return IsClipboardFormatAvailable( wFormat
);
1207 /**************************************************************************
1208 * IsClipboardFormatAvailable32 (USER32.340)
1210 BOOL WINAPI
IsClipboardFormatAvailable( UINT wFormat
)
1214 if (wFormat
== 0) /* Reject this case quickly */
1217 /* If WINE is not the clipboard selection owner ask the clipboard driver */
1218 else if ( !CLIPBOARD_Driver
->pIsSelectionOwner() )
1219 bRet
= CLIPBOARD_Driver
->pIsFormatAvailable( (wFormat
== CF_TEXT
) ?
1220 CF_OEMTEXT
: wFormat
);
1221 /* Check if the format is in the local cache */
1223 bRet
= CLIPBOARD_IsPresent(wFormat
);
1225 TRACE("(%04X)- ret(%d)\n", wFormat
, bRet
);
1230 /**************************************************************************
1231 * GetOpenClipboardWindow16 (USER.248)
1232 * FIXME: This wont work if an external app owns the selection
1234 HWND16 WINAPI
GetOpenClipboardWindow16(void)
1237 return hWndClipWindow
;
1241 /**************************************************************************
1242 * GetOpenClipboardWindow32 (USER32.277)
1243 * FIXME: This wont work if an external app owns the selection
1245 HWND WINAPI
GetOpenClipboardWindow(void)
1248 return hWndClipWindow
;
1252 /**************************************************************************
1253 * GetPriorityClipboardFormat16 (USER.402)
1255 INT16 WINAPI
GetPriorityClipboardFormat16( UINT16
*lpPriorityList
, INT16 nCount
)
1257 FIXME("(%p,%d): stub\n", lpPriorityList
, nCount
);
1262 /**************************************************************************
1263 * GetPriorityClipboardFormat32 (USER32.279)
1265 INT WINAPI
GetPriorityClipboardFormat( UINT
*lpPriorityList
, INT nCount
)
1270 if(CountClipboardFormats() == 0)
1275 for(Counter
= 0; Counter
<= nCount
; Counter
++)
1277 if(IsClipboardFormatAvailable(*(lpPriorityList
+sizeof(INT
)*Counter
)))
1278 return *(lpPriorityList
+sizeof(INT
)*Counter
);