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>
29 #include "wine/winuser16.h"
30 #include "wine/winbase16.h"
36 #include "clipboard.h"
37 #include "debugtools.h"
39 DEFAULT_DEBUG_CHANNEL(clipboard
);
41 #define CF_REGFORMATBASE 0xC000
43 /**************************************************************************
44 * Clipboard context global variables
47 static HANDLE hClipLock
= 0;
48 static BOOL bCBHasChanged
= FALSE
;
50 HWND hWndClipWindow
= 0; /* window that last opened clipboard */
51 HWND hWndClipOwner
= 0; /* current clipboard owner */
52 HANDLE16 hTaskClipOwner
= 0; /* clipboard owner's task */
53 static HWND hWndViewer
= 0; /* start of viewers chain */
55 static WORD LastRegFormat
= CF_REGFORMATBASE
;
57 /* Clipboard cache initial data.
58 * WARNING: This data ordering is dependendent on the WINE_CLIPFORMAT structure
59 * declared in clipboard.h
61 WINE_CLIPFORMAT ClipFormats
[17] = {
62 { CF_TEXT
, 1, 0, "Text", 0, 0, 0, 0, NULL
, &ClipFormats
[1]},
63 { CF_BITMAP
, 1, 0, "Bitmap", 0, 0, 0, 0, &ClipFormats
[0], &ClipFormats
[2]},
64 { CF_METAFILEPICT
, 1, 0, "MetaFile Picture", 0, 0, 0, 0, &ClipFormats
[1], &ClipFormats
[3]},
65 { CF_SYLK
, 1, 0, "Sylk", 0, 0, 0, 0, &ClipFormats
[2], &ClipFormats
[4]},
66 { CF_DIF
, 1, 0, "DIF", 0, 0, 0, 0, &ClipFormats
[3], &ClipFormats
[5]},
67 { CF_TIFF
, 1, 0, "TIFF", 0, 0, 0, 0, &ClipFormats
[4], &ClipFormats
[6]},
68 { CF_OEMTEXT
, 1, 0, "OEM Text", 0, 0, 0, 0, &ClipFormats
[5], &ClipFormats
[7]},
69 { CF_DIB
, 1, 0, "DIB", 0, 0, 0, 0, &ClipFormats
[6], &ClipFormats
[8]},
70 { CF_PALETTE
, 1, 0, "Palette", 0, 0, 0, 0, &ClipFormats
[7], &ClipFormats
[9]},
71 { CF_PENDATA
, 1, 0, "PenData", 0, 0, 0, 0, &ClipFormats
[8], &ClipFormats
[10]},
72 { CF_RIFF
, 1, 0, "RIFF", 0, 0, 0, 0, &ClipFormats
[9], &ClipFormats
[11]},
73 { CF_WAVE
, 1, 0, "Wave", 0, 0, 0, 0, &ClipFormats
[10], &ClipFormats
[12]},
74 { CF_OWNERDISPLAY
, 1, 0, "Owner Display", 0, 0, 0, 0, &ClipFormats
[11], &ClipFormats
[13]},
75 { CF_DSPTEXT
, 1, 0, "DSPText", 0, 0, 0, 0, &ClipFormats
[12], &ClipFormats
[14]},
76 { CF_DSPMETAFILEPICT
, 1, 0, "DSPMetaFile Picture", 0, 0, 0, 0, &ClipFormats
[13], &ClipFormats
[15]},
77 { CF_DSPBITMAP
, 1, 0, "DSPBitmap", 0, 0, 0, 0, &ClipFormats
[14], &ClipFormats
[16]},
78 { CF_HDROP
, 1, 0, "HDROP", 0, 0, 0, 0, &ClipFormats
[15], NULL
}
82 /**************************************************************************
83 * Internal Clipboard implementation methods
84 **************************************************************************/
87 /**************************************************************************
88 * CLIPBOARD_LookupFormat
90 static LPWINE_CLIPFORMAT
__lookup_format( LPWINE_CLIPFORMAT lpFormat
, WORD wID
)
94 if (lpFormat
== NULL
||
95 lpFormat
->wFormatID
== wID
) break;
96 lpFormat
= lpFormat
->NextFormat
;
101 LPWINE_CLIPFORMAT
CLIPBOARD_LookupFormat( WORD wID
)
103 return __lookup_format( ClipFormats
, wID
);
106 /**************************************************************************
108 * Check if the clipboard cache is available to the caller
110 BOOL
CLIPBOARD_IsLocked()
112 BOOL bIsLocked
= TRUE
;
113 HANDLE16 hTaskCur
= GetCurrentTask();
116 * The clipboard is available:
117 * 1. if the caller's task has opened the clipboard,
119 * 2. if the caller is the clipboard owners task, AND is responding to a
120 * WM_RENDERFORMAT message.
122 if ( hClipLock
== hTaskCur
)
125 else if ( hTaskCur
== hTaskClipOwner
)
127 /* Check if we're currently executing inside a window procedure
128 * called in response to a WM_RENDERFORMAT message. A WM_RENDERFORMAT
129 * handler is not permitted to open the clipboard since it has been opened
130 * by another client. However the handler must have access to the
131 * clipboard in order to update data in response to this message.
133 MESSAGEQUEUE
*queue
= QUEUE_Lock( GetFastQueue16() );
137 && queue
->smWaiting
->msg
== WM_RENDERFORMAT
138 && queue
->smWaiting
->hSrcQueue
142 QUEUE_Unlock( queue
);
148 /**************************************************************************
149 * CLIPBOARD_ReleaseOwner
150 * Gives up ownership of the clipboard
152 void CLIPBOARD_ReleaseOwner()
158 /**************************************************************************
159 * CLIPBOARD_GlobalFreeProc
161 * This is a callback mechanism to allow HGLOBAL data to be released in
162 * the context of the process which allocated it. We post a WM_TIMER message
163 * to the owner window(in CLIPBOARD_DeleteRecord) and destroy the data(in idEvent)
164 * in this WndProc, which is invoked when the apps message loop calls DispatchMessage.
165 * This technique is discussed in Matt Pietrek's "Under the Hood".
166 * An article describing the same may be found in MSDN by searching for WM_TIMER.
167 * Note that this mechanism will probably stop working when WINE supports
168 * address space separation. When "queue events" are implemented in Wine we
169 * should switch to using that mechanism, since it is more robust and does not
170 * require a procedure address to be passed. See the SetWinEventHook API for
173 VOID CALLBACK
CLIPBOARD_GlobalFreeProc( HWND hwnd
, UINT uMsg
, UINT idEvent
, DWORD dwTime
)
175 /* idEvent is the HGLOBAL to be deleted */
176 GlobalFree( (HGLOBAL
)idEvent
);
179 /**************************************************************************
180 * CLIPBOARD_DeleteRecord
182 void CLIPBOARD_DeleteRecord(LPWINE_CLIPFORMAT lpFormat
, BOOL bChange
)
184 if( (lpFormat
->wFormatID
>= CF_GDIOBJFIRST
&&
185 lpFormat
->wFormatID
<= CF_GDIOBJLAST
) || lpFormat
->wFormatID
== CF_BITMAP
186 || lpFormat
->wFormatID
== CF_PALETTE
)
188 if (lpFormat
->hData32
)
189 DeleteObject(lpFormat
->hData32
);
190 if (lpFormat
->hData16
)
191 DeleteObject(lpFormat
->hData16
);
193 else if( lpFormat
->wFormatID
== CF_METAFILEPICT
)
195 if (lpFormat
->hData32
)
197 DeleteMetaFile( ((METAFILEPICT
*)GlobalLock( lpFormat
->hData32
))->hMF
);
198 PostMessageA(hWndClipOwner
, WM_TIMER
,
199 (WPARAM
)lpFormat
->hData32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
200 if (lpFormat
->hDataSrc32
)
202 /* Release lpFormat->hData32 in the context of the process which created it.
203 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
204 * GlobalFree(lpFormat->hDataSrc32);
206 PostMessageA(hWndClipOwner
, WM_TIMER
,
207 (WPARAM
)lpFormat
->hDataSrc32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
210 if (lpFormat
->hData16
)
211 /* HMETAFILE16 and HMETAFILE32 are apparently the same thing,
212 and a shallow copy is enough to share a METAFILEPICT
213 structure between 16bit and 32bit clipboards. The MetaFile
214 should of course only be deleted once. */
215 GlobalFree16(lpFormat
->hData16
);
217 if (lpFormat
->hData16
)
219 DeleteMetaFile16( ((METAFILEPICT16
*)GlobalLock16( lpFormat
->hData16
))->hMF
);
220 GlobalFree16(lpFormat
->hData16
);
225 if (lpFormat
->hData32
)
227 /* Release lpFormat->hData32 in the context of the process which created it.
228 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
229 * GlobalFree( lpFormat->hData32 );
231 PostMessageA(hWndClipOwner
, WM_TIMER
,
232 (WPARAM
)lpFormat
->hData32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
234 if (lpFormat
->hDataSrc32
)
236 /* Release lpFormat->hData32 in the context of the process which created it.
237 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
238 * GlobalFree(lpFormat->hDataSrc32);
240 PostMessageA(hWndClipOwner
, WM_TIMER
,
241 (WPARAM
)lpFormat
->hDataSrc32
, (LPARAM
)CLIPBOARD_GlobalFreeProc
);
243 if (lpFormat
->hData16
)
244 GlobalFree16(lpFormat
->hData16
);
247 lpFormat
->wDataPresent
= 0;
248 lpFormat
->hData16
= 0;
249 lpFormat
->hData32
= 0;
250 lpFormat
->hDataSrc32
= 0;
251 lpFormat
->drvData
= 0;
253 if( bChange
) bCBHasChanged
= TRUE
;
256 /**************************************************************************
257 * CLIPBOARD_EmptyCache
259 void CLIPBOARD_EmptyCache( BOOL bChange
)
261 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
265 if ( lpFormat
->wDataPresent
|| lpFormat
->hData16
|| lpFormat
->hData32
)
266 CLIPBOARD_DeleteRecord( lpFormat
, bChange
);
268 lpFormat
= lpFormat
->NextFormat
;
272 /**************************************************************************
273 * CLIPBOARD_IsPresent
275 BOOL
CLIPBOARD_IsPresent(WORD wFormat
)
279 if( wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
)
280 return ClipFormats
[CF_TEXT
-1].wDataPresent
||
281 ClipFormats
[CF_OEMTEXT
-1].wDataPresent
;
284 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
285 if( lpFormat
) return (lpFormat
->wDataPresent
);
290 /**************************************************************************
291 * CLIPBOARD_IsCacheRendered
292 * Checks if any data needs to be rendered to the clipboard cache
294 * TRUE - All clipboard data is available in the cache
295 * FALSE - Some data is marked for delayed render and needs rendering
297 BOOL
CLIPBOARD_IsCacheRendered()
299 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
301 /* check if all formats were rendered */
304 if( lpFormat
->wDataPresent
&& !lpFormat
->hData16
&& !lpFormat
->hData32
)
307 lpFormat
= lpFormat
->NextFormat
;
314 /**************************************************************************
315 * CLIPBOARD_IsMemoryObject
316 * Tests if the clipboard format specifies a memory object
318 BOOL
CLIPBOARD_IsMemoryObject( WORD wFormat
)
323 case CF_METAFILEPICT
:
335 /***********************************************************************
336 * CLIPBOARD_GlobalDupMem( HGLOBAL )
337 * Helper method to duplicate an HGLOBAL chunk of memory into shared memory
339 HGLOBAL
CLIPBOARD_GlobalDupMem( HGLOBAL hGlobalSrc
)
342 PVOID pGlobalSrc
, pGlobalDest
;
348 cBytes
= GlobalSize(hGlobalSrc
);
352 /* Turn on the DDESHARE and _MOVEABLE flags explicitly */
353 hGlobalDest
= GlobalAlloc( GlobalFlags(hGlobalSrc
) | GMEM_DDESHARE
| GMEM_MOVEABLE
,
358 pGlobalSrc
= GlobalLock(hGlobalSrc
);
359 pGlobalDest
= GlobalLock(hGlobalDest
);
360 if ( !pGlobalSrc
|| !pGlobalDest
)
363 memcpy(pGlobalDest
, pGlobalSrc
, cBytes
);
365 GlobalUnlock(hGlobalSrc
);
366 GlobalUnlock(hGlobalDest
);
371 /**************************************************************************
372 * CLIPBOARD_GetFormatName
373 * Gets the format name associated with an ID
375 char * CLIPBOARD_GetFormatName(UINT wFormat
)
377 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
378 return (lpFormat
) ? lpFormat
->Name
: NULL
;
382 /**************************************************************************
383 * CLIPBOARD_RenderFormat
385 static BOOL
CLIPBOARD_RenderFormat(LPWINE_CLIPFORMAT lpFormat
)
388 * If WINE is not the selection owner, and the format is available
389 * we must ask the the driver to render the data to the clipboard cache.
391 if ( !USER_Driver
.pIsSelectionOwner()
392 && USER_Driver
.pIsClipboardFormatAvailable( lpFormat
->wFormatID
) )
394 if ( !USER_Driver
.pGetClipboardData( lpFormat
->wFormatID
) )
398 * If Wine owns the clipboard, and the data is marked for delayed render,
401 else if( lpFormat
->wDataPresent
&& !lpFormat
->hData16
&& !lpFormat
->hData32
)
403 if( IsWindow(hWndClipOwner
) )
405 /* Send a WM_RENDERFORMAT message to notify the owner to render the
406 * data requested into the clipboard.
408 TRACE("Sending WM_RENDERFORMAT message\n");
409 SendMessage16(hWndClipOwner
,WM_RENDERFORMAT
,
410 (WPARAM16
)lpFormat
->wFormatID
,0L);
414 WARN("\thWndClipOwner (%04x) is lost!\n",
416 CLIPBOARD_ReleaseOwner();
417 lpFormat
->wDataPresent
= 0;
422 return (lpFormat
->hData16
|| lpFormat
->hData32
) ? TRUE
: FALSE
;
426 /**************************************************************************
427 * CLIPBOARD_RenderText
429 * Renders text to the clipboard buffer converting between UNIX and DOS formats.
431 * RETURNS: pointer to the WINE_CLIPFORMAT if successful, NULL otherwise
433 * FIXME: Should be a pair of driver functions that convert between OEM text and Windows.
436 static LPWINE_CLIPFORMAT
CLIPBOARD_RenderText( UINT wFormat
)
438 LPWINE_CLIPFORMAT lpSource
= ClipFormats
;
439 LPWINE_CLIPFORMAT lpTarget
;
441 /* Asked for CF_TEXT and not available - always attempt to convert from CF_OEM_TEXT */
442 if( wFormat
== CF_TEXT
&& !ClipFormats
[CF_TEXT
-1].wDataPresent
)
444 /* Convert OEMTEXT -> TEXT */
445 lpSource
= &ClipFormats
[CF_OEMTEXT
-1];
446 lpTarget
= &ClipFormats
[CF_TEXT
-1];
448 TRACE("\tOEMTEXT -> TEXT\n");
450 /* Asked for CF_OEM_TEXT, and CF_TEXT available */
451 else if( wFormat
== CF_OEMTEXT
&& !ClipFormats
[CF_OEMTEXT
-1].wDataPresent
452 && ClipFormats
[CF_TEXT
-1].wDataPresent
)
454 /* Convert TEXT -> OEMTEXT */
455 lpSource
= &ClipFormats
[CF_TEXT
-1];
456 lpTarget
= &ClipFormats
[CF_OEMTEXT
-1];
458 TRACE("\tTEXT -> OEMTEXT\n");
460 /* Text format requested is available - no conversion necessary */
463 lpSource
= __lookup_format( ClipFormats
, wFormat
);
467 /* First render the source text format */
468 if ( !lpSource
|| !CLIPBOARD_RenderFormat(lpSource
) ) return NULL
;
470 /* Convert to the desired target text format, if necessary */
471 if( lpTarget
!= lpSource
&& !lpTarget
->hData16
&& !lpTarget
->hData32
)
477 if (lpSource
->hData32
)
479 size
= GlobalSize( lpSource
->hData32
);
480 lpstrS
= (LPSTR
)GlobalLock(lpSource
->hData32
);
484 size
= GlobalSize16( lpSource
->hData16
);
485 lpstrS
= (LPSTR
)GlobalLock16(lpSource
->hData16
);
488 if( !lpstrS
) return NULL
;
489 TRACE("\tconverting from '%s' to '%s', %i chars\n",
490 lpSource
->Name
, lpTarget
->Name
, size
);
492 lpTarget
->hData32
= GlobalAlloc(GMEM_ZEROINIT
| GMEM_MOVEABLE
| GMEM_DDESHARE
, size
);
493 lpstrT
= (LPSTR
)GlobalLock(lpTarget
->hData32
);
497 if( lpSource
->wFormatID
== CF_TEXT
)
498 CharToOemBuffA(lpstrS
, lpstrT
, size
);
500 OemToCharBuffA(lpstrS
, lpstrT
, size
);
501 TRACE("\tgot %s\n", lpstrT
);
502 GlobalUnlock(lpTarget
->hData32
);
505 lpTarget
->hData32
= 0;
508 if (lpSource
->hData32
)
509 GlobalUnlock(lpSource
->hData32
);
511 GlobalUnlock16(lpSource
->hData16
);
514 return (lpTarget
->hData16
|| lpTarget
->hData32
) ? lpTarget
: NULL
;
517 /**************************************************************************
518 * WIN32 Clipboard implementation
519 **************************************************************************/
521 /**************************************************************************
522 * OpenClipboard16 (USER.137)
524 BOOL16 WINAPI
OpenClipboard16( HWND16 hWnd
)
526 return OpenClipboard( hWnd
);
530 /**************************************************************************
531 * OpenClipboard (USER32.407)
533 * Note: Netscape uses NULL hWnd to open the clipboard.
535 BOOL WINAPI
OpenClipboard( HWND hWnd
)
539 TRACE("(%04x)...\n", hWnd
);
543 hClipLock
= GetCurrentTask();
545 /* Save current user of the clipboard */
546 hWndClipWindow
= hWnd
;
547 bCBHasChanged
= FALSE
;
552 TRACE(" returning %i\n", bRet
);
557 /**************************************************************************
558 * CloseClipboard16 (USER.138)
560 BOOL16 WINAPI
CloseClipboard16(void)
562 return CloseClipboard();
566 /**************************************************************************
567 * CloseClipboard (USER32.54)
569 BOOL WINAPI
CloseClipboard(void)
573 if (hClipLock
== GetCurrentTask())
577 if (bCBHasChanged
&& hWndViewer
)
578 SendMessage16(hWndViewer
, WM_DRAWCLIPBOARD
, 0, 0L);
585 /**************************************************************************
586 * EmptyClipboard16 (USER.139)
588 BOOL16 WINAPI
EmptyClipboard16(void)
590 return EmptyClipboard();
594 /**************************************************************************
595 * EmptyClipboard (USER32.169)
596 * Empties and acquires ownership of the clipboard
598 BOOL WINAPI
EmptyClipboard(void)
602 if (hClipLock
!= GetCurrentTask())
604 WARN("Clipboard not opened by calling task!");
608 /* destroy private objects */
611 SendMessage16(hWndClipOwner
, WM_DESTROYCLIPBOARD
, 0, 0L);
613 /* empty the cache */
614 CLIPBOARD_EmptyCache(TRUE
);
616 /* Assign ownership of the clipboard to the current client */
617 hWndClipOwner
= hWndClipWindow
;
619 /* Save the current task */
620 hTaskClipOwner
= GetCurrentTask();
622 /* Tell the driver to acquire the selection */
623 USER_Driver
.pAcquireClipboard();
629 /**************************************************************************
630 * GetClipboardOwner16 (USER.140)
631 * FIXME: Can't return the owner if the clipbard is owned by an external app
633 HWND16 WINAPI
GetClipboardOwner16(void)
636 return hWndClipOwner
;
640 /**************************************************************************
641 * GetClipboardOwner (USER32.225)
642 * FIXME: Can't return the owner if the clipbard is owned by an external app
644 HWND WINAPI
GetClipboardOwner(void)
647 return hWndClipOwner
;
651 /**************************************************************************
652 * SetClipboardData16 (USER.141)
654 HANDLE16 WINAPI
SetClipboardData16( UINT16 wFormat
, HANDLE16 hData
)
656 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
658 TRACE("(%04X, %04x) !\n", wFormat
, hData
);
660 /* NOTE: If the hData is zero and current owner doesn't match
661 * the window that opened the clipboard then this application
662 * is screwed because WM_RENDERFORMAT will go to the owner.
663 * (to become the owner it must call EmptyClipboard() before
667 if( CLIPBOARD_IsLocked() || !lpFormat
||
668 (!hData
&& (!hWndClipOwner
|| (hWndClipOwner
!= hWndClipWindow
))) )
670 WARN("Invalid hData or clipboard not opened by calling task!\n");
674 /* Pass on the request to the driver */
675 USER_Driver
.pSetClipboardData(wFormat
);
677 if ( lpFormat
->wDataPresent
|| lpFormat
->hData16
|| lpFormat
->hData32
)
679 CLIPBOARD_DeleteRecord(lpFormat
, TRUE
);
681 /* delete existing CF_TEXT/CF_OEMTEXT aliases */
683 if( wFormat
== CF_TEXT
684 && ( ClipFormats
[CF_OEMTEXT
-1].hData16
685 || ClipFormats
[CF_OEMTEXT
-1].hData32
)
686 && !ClipFormats
[CF_OEMTEXT
-1].wDataPresent
)
687 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
688 if( wFormat
== CF_OEMTEXT
689 && ( ClipFormats
[CF_OEMTEXT
-1].hData16
690 || ClipFormats
[CF_OEMTEXT
-1].hData32
)
691 && !ClipFormats
[CF_TEXT
-1].wDataPresent
)
692 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
695 bCBHasChanged
= TRUE
;
696 lpFormat
->wDataPresent
= 1;
697 lpFormat
->hData16
= hData
; /* 0 is legal, see WM_RENDERFORMAT */
698 lpFormat
->hData32
= 0;
700 return lpFormat
->hData16
;
704 /**************************************************************************
705 * SetClipboardData (USER32.470)
707 HANDLE WINAPI
SetClipboardData( UINT wFormat
, HANDLE hData
)
709 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
711 TRACE("(%08X, %08x) !\n", wFormat
, hData
);
713 /* NOTE: If the hData is zero and current owner doesn't match
714 * the window that opened the clipboard then this application
715 * is screwed because WM_RENDERFORMAT will go to the owner.
716 * (to become the owner it must call EmptyClipboard() before
720 if( CLIPBOARD_IsLocked() || !lpFormat
||
721 (!hData
&& (!hWndClipOwner
|| (hWndClipOwner
!= hWndClipWindow
))) )
723 WARN("Invalid hData or clipboard not opened by calling task!\n");
727 /* Tell the driver to acquire the selection */
728 USER_Driver
.pAcquireClipboard();
730 if ( lpFormat
->wDataPresent
&&
731 (lpFormat
->hData16
|| lpFormat
->hData32
) )
733 CLIPBOARD_DeleteRecord(lpFormat
, TRUE
);
735 /* delete existing CF_TEXT/CF_OEMTEXT aliases */
737 if( wFormat
== CF_TEXT
738 && ( ClipFormats
[CF_OEMTEXT
-1].hData16
739 || ClipFormats
[CF_OEMTEXT
-1].hData32
)
740 && !ClipFormats
[CF_OEMTEXT
-1].wDataPresent
)
741 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
742 if( wFormat
== CF_OEMTEXT
743 && ( ClipFormats
[CF_OEMTEXT
-1].hData16
744 || ClipFormats
[CF_OEMTEXT
-1].hData32
)
745 && !ClipFormats
[CF_TEXT
-1].wDataPresent
)
746 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
749 bCBHasChanged
= TRUE
;
750 lpFormat
->wDataPresent
= 1;
751 lpFormat
->hDataSrc32
= hData
; /* Save the source handle */
754 * Make a shared duplicate if the memory is not shared
755 * TODO: What should be done for non-memory objects
757 if ( CLIPBOARD_IsMemoryObject(wFormat
) && hData
&& !(GlobalFlags(hData
) & GMEM_DDESHARE
) )
758 lpFormat
->hData32
= CLIPBOARD_GlobalDupMem( hData
);
760 lpFormat
->hData32
= hData
; /* 0 is legal, see WM_RENDERFORMAT */
762 lpFormat
->hData16
= 0;
764 return lpFormat
->hData32
; /* Should we return lpFormat->hDataSrc32 */
768 /**************************************************************************
769 * GetClipboardData16 (USER.142)
771 HANDLE16 WINAPI
GetClipboardData16( UINT16 wFormat
)
773 LPWINE_CLIPFORMAT lpRender
= ClipFormats
;
775 TRACE("(%04X)\n", wFormat
);
777 if (CLIPBOARD_IsLocked())
779 WARN("Clipboard not opened by calling task!\n");
783 if( wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
)
785 lpRender
= CLIPBOARD_RenderText(wFormat
);
786 if ( !lpRender
) return 0;
790 lpRender
= __lookup_format( ClipFormats
, wFormat
);
791 if( !lpRender
|| !CLIPBOARD_RenderFormat(lpRender
) ) return 0;
794 /* Convert between 32 -> 16 bit data, if necessary */
795 if( lpRender
->hData32
&& !lpRender
->hData16
796 && CLIPBOARD_IsMemoryObject(wFormat
) )
799 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
800 size
= sizeof( METAFILEPICT16
);
802 size
= GlobalSize(lpRender
->hData32
);
804 lpRender
->hData16
= GlobalAlloc16(GMEM_ZEROINIT
, size
);
805 if( !lpRender
->hData16
)
806 ERR("(%04X) -- not enough memory in 16b heap\n", wFormat
);
809 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
811 FIXME("\timplement function CopyMetaFilePict32to16\n");
812 FIXME("\tin the appropriate file.\n");
813 #ifdef SOMEONE_IMPLEMENTED_ME
814 CopyMetaFilePict32to16( GlobalLock16(lpRender
->hData16
),
815 GlobalLock(lpRender
->hData32
) );
820 memcpy( GlobalLock16(lpRender
->hData16
),
821 GlobalLock(lpRender
->hData32
),
824 GlobalUnlock16(lpRender
->hData16
);
825 GlobalUnlock(lpRender
->hData32
);
829 TRACE("\treturning %04x (type %i)\n",
830 lpRender
->hData16
, lpRender
->wFormatID
);
831 return lpRender
->hData16
;
835 /**************************************************************************
836 * GetClipboardData (USER32.222)
838 HANDLE WINAPI
GetClipboardData( UINT wFormat
)
840 LPWINE_CLIPFORMAT lpRender
= ClipFormats
;
842 TRACE("(%08X)\n", wFormat
);
844 if (CLIPBOARD_IsLocked())
846 WARN("Clipboard not opened by calling task!");
850 if( wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
)
852 lpRender
= CLIPBOARD_RenderText(wFormat
);
853 if ( !lpRender
) return 0;
857 lpRender
= __lookup_format( ClipFormats
, wFormat
);
858 if( !lpRender
|| !CLIPBOARD_RenderFormat(lpRender
) ) return 0;
861 /* Convert between 16 -> 32 bit data, if necessary */
862 if( lpRender
->hData16
&& !lpRender
->hData32
863 && CLIPBOARD_IsMemoryObject(wFormat
) )
866 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
867 size
= sizeof( METAFILEPICT
);
869 size
= GlobalSize16(lpRender
->hData16
);
870 lpRender
->hData32
= GlobalAlloc(GMEM_ZEROINIT
| GMEM_MOVEABLE
| GMEM_DDESHARE
,
872 if( lpRender
->wFormatID
== CF_METAFILEPICT
)
874 FIXME("\timplement function CopyMetaFilePict16to32\n");
875 FIXME("\tin the appropriate file.\n");
876 #ifdef SOMEONE_IMPLEMENTED_ME
877 CopyMetaFilePict16to32( GlobalLock16(lpRender
->hData32
),
878 GlobalLock(lpRender
->hData16
) );
883 memcpy( GlobalLock(lpRender
->hData32
),
884 GlobalLock16(lpRender
->hData16
),
887 GlobalUnlock(lpRender
->hData32
);
888 GlobalUnlock16(lpRender
->hData16
);
891 TRACE("\treturning %04x (type %i)\n",
892 lpRender
->hData32
, lpRender
->wFormatID
);
893 return lpRender
->hData32
;
897 /**************************************************************************
898 * CountClipboardFormats16 (USER.143)
900 INT16 WINAPI
CountClipboardFormats16(void)
902 return CountClipboardFormats();
906 /**************************************************************************
907 * CountClipboardFormats (USER32.63)
909 INT WINAPI
CountClipboardFormats(void)
912 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
918 if (lpFormat
== NULL
) break;
920 if( lpFormat
->wFormatID
!= CF_TEXT
) /* Don't count CF_TEXT */
923 * The format is available if either:
924 * 1. The data is already in the cache.
925 * 2. The selection is not owned by us(WINE) and the data is
926 * available to the clipboard driver.
928 if ( lpFormat
->wDataPresent
||
929 ( !USER_Driver
.pIsSelectionOwner()
930 && USER_Driver
.pIsClipboardFormatAvailable( lpFormat
->wFormatID
) ) )
932 TRACE("\tdata found for format 0x%04x(%s)\n",
933 lpFormat
->wFormatID
, CLIPBOARD_GetFormatName(lpFormat
->wFormatID
));
938 lpFormat
= lpFormat
->NextFormat
;
941 /* these two are equivalent, adjust the total */
943 FormatCount
+= abs(ClipFormats
[CF_TEXT
-1].wDataPresent
-
944 ClipFormats
[CF_OEMTEXT
-1].wDataPresent
);
946 TRACE("\ttotal %d\n", FormatCount
);
951 /**************************************************************************
952 * EnumClipboardFormats16 (USER.144)
954 UINT16 WINAPI
EnumClipboardFormats16( UINT16 wFormat
)
956 return EnumClipboardFormats( wFormat
);
960 /**************************************************************************
961 * EnumClipboardFormats (USER32.179)
963 UINT WINAPI
EnumClipboardFormats( UINT wFormat
)
965 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
968 TRACE("(%04X)\n", wFormat
);
970 if (CLIPBOARD_IsLocked())
972 WARN("Clipboard not opened by calling task!");
976 if (wFormat
== 0) /* start from the beginning */
977 lpFormat
= ClipFormats
;
980 /* walk up to the specified format record */
982 if( !(lpFormat
= __lookup_format( lpFormat
, wFormat
)) )
984 lpFormat
= lpFormat
->NextFormat
; /* right */
989 if (lpFormat
== NULL
) return 0;
991 /* Synthesize CF_TEXT from CF_OEMTEXT and vice versa */
992 bFormatPresent
= (lpFormat
->wDataPresent
||
993 (lpFormat
->wFormatID
== CF_OEMTEXT
&& ClipFormats
[CF_TEXT
-1].wDataPresent
) ||
994 (lpFormat
->wFormatID
== CF_TEXT
&& ClipFormats
[CF_OEMTEXT
-1].wDataPresent
) );
996 /* Query the driver if not yet in the cache */
997 if (!bFormatPresent
&& !USER_Driver
.pIsSelectionOwner())
1000 USER_Driver
.pIsClipboardFormatAvailable( (lpFormat
->wFormatID
== CF_TEXT
) ?
1001 CF_OEMTEXT
: lpFormat
->wFormatID
);
1007 lpFormat
= lpFormat
->NextFormat
;
1010 return lpFormat
->wFormatID
;
1014 /**************************************************************************
1015 * RegisterClipboardFormat16 (USER.145)
1017 UINT16 WINAPI
RegisterClipboardFormat16( LPCSTR FormatName
)
1019 LPWINE_CLIPFORMAT lpNewFormat
;
1020 LPWINE_CLIPFORMAT lpFormat
= ClipFormats
;
1022 if (FormatName
== NULL
) return 0;
1024 TRACE("('%s') !\n", FormatName
);
1026 /* walk format chain to see if it's already registered */
1030 if ( !strcmp(lpFormat
->Name
,FormatName
) )
1032 lpFormat
->wRefCount
++;
1033 return lpFormat
->wFormatID
;
1036 if ( lpFormat
->NextFormat
== NULL
) break;
1038 lpFormat
= lpFormat
->NextFormat
;
1041 /* allocate storage for new format entry */
1043 lpNewFormat
= (LPWINE_CLIPFORMAT
)HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_CLIPFORMAT
));
1044 if(lpNewFormat
== NULL
) {
1045 WARN("No more memory for a new format!");
1048 lpFormat
->NextFormat
= lpNewFormat
;
1049 lpNewFormat
->wFormatID
= LastRegFormat
;
1050 lpNewFormat
->wRefCount
= 1;
1052 lpNewFormat
->Name
= (LPSTR
)HEAP_strdupA(GetProcessHeap(), 0, FormatName
);
1053 if(lpNewFormat
->Name
== NULL
) {
1054 WARN("No more memory for the new format name!");
1055 HeapFree(GetProcessHeap(), 0, lpNewFormat
);
1059 lpNewFormat
->wDataPresent
= 0;
1060 lpNewFormat
->hData16
= 0;
1061 lpNewFormat
->hDataSrc32
= 0;
1062 lpNewFormat
->hData32
= 0;
1063 lpNewFormat
->drvData
= 0;
1064 lpNewFormat
->PrevFormat
= lpFormat
;
1065 lpNewFormat
->NextFormat
= NULL
;
1067 /* Pass on the registration request to the driver */
1068 USER_Driver
.pRegisterClipboardFormat( FormatName
);
1070 return LastRegFormat
++;
1074 /**************************************************************************
1075 * RegisterClipboardFormatA (USER32.431)
1077 UINT WINAPI
RegisterClipboardFormatA( LPCSTR formatName
)
1079 return RegisterClipboardFormat16( formatName
);
1083 /**************************************************************************
1084 * RegisterClipboardFormatW (USER32.432)
1086 UINT WINAPI
RegisterClipboardFormatW( LPCWSTR formatName
)
1088 LPSTR aFormat
= HEAP_strdupWtoA( GetProcessHeap(), 0, formatName
);
1089 UINT ret
= RegisterClipboardFormatA( aFormat
);
1090 HeapFree( GetProcessHeap(), 0, aFormat
);
1095 /**************************************************************************
1096 * GetClipboardFormatName16 (USER.146)
1098 INT16 WINAPI
GetClipboardFormatName16( UINT16 wFormat
, LPSTR retStr
, INT16 maxlen
)
1100 return GetClipboardFormatNameA( wFormat
, retStr
, maxlen
);
1104 /**************************************************************************
1105 * GetClipboardFormatNameA (USER32.223)
1107 INT WINAPI
GetClipboardFormatNameA( UINT wFormat
, LPSTR retStr
, INT maxlen
)
1109 LPWINE_CLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
1111 TRACE("(%04X, %p, %d) !\n", wFormat
, retStr
, maxlen
);
1113 if (lpFormat
== NULL
|| lpFormat
->Name
== NULL
||
1114 lpFormat
->wFormatID
< CF_REGFORMATBASE
) return 0;
1116 TRACE("Name='%s' !\n", lpFormat
->Name
);
1118 lstrcpynA( retStr
, lpFormat
->Name
, maxlen
);
1119 return strlen(retStr
);
1123 /**************************************************************************
1124 * GetClipboardFormatNameW (USER32.224)
1126 INT WINAPI
GetClipboardFormatNameW( UINT wFormat
, LPWSTR retStr
, INT maxlen
)
1129 LPSTR p
= HeapAlloc( GetProcessHeap(), 0, maxlen
);
1130 if(p
== NULL
) return 0; /* FIXME: is this the correct failure value? */
1132 ret
= GetClipboardFormatNameA( wFormat
, p
, maxlen
);
1133 lstrcpynAtoW( retStr
, p
, maxlen
);
1134 HeapFree( GetProcessHeap(), 0, p
);
1139 /**************************************************************************
1140 * SetClipboardViewer16 (USER.147)
1142 HWND16 WINAPI
SetClipboardViewer16( HWND16 hWnd
)
1144 TRACE("(%04x)\n", hWnd
);
1145 return SetClipboardViewer( hWnd
);
1149 /**************************************************************************
1150 * SetClipboardViewer (USER32.471)
1152 HWND WINAPI
SetClipboardViewer( HWND hWnd
)
1154 HWND hwndPrev
= hWndViewer
;
1156 TRACE("(%04x): returning %04x\n", hWnd
, hwndPrev
);
1163 /**************************************************************************
1164 * GetClipboardViewer16 (USER.148)
1166 HWND16 WINAPI
GetClipboardViewer16(void)
1173 /**************************************************************************
1174 * GetClipboardViewer (USER32.226)
1176 HWND WINAPI
GetClipboardViewer(void)
1183 /**************************************************************************
1184 * ChangeClipboardChain16 (USER.149)
1186 BOOL16 WINAPI
ChangeClipboardChain16(HWND16 hWnd
, HWND16 hWndNext
)
1188 return ChangeClipboardChain(hWnd
, hWndNext
);
1192 /**************************************************************************
1193 * ChangeClipboardChain (USER32.22)
1195 BOOL WINAPI
ChangeClipboardChain(HWND hWnd
, HWND hWndNext
)
1199 FIXME("(0x%04x, 0x%04x): stub?\n", hWnd
, hWndNext
);
1202 bRet
= !SendMessage16( hWndViewer
, WM_CHANGECBCHAIN
,
1203 (WPARAM16
)hWnd
, (LPARAM
)hWndNext
);
1205 WARN("hWndViewer is lost\n");
1207 if( hWnd
== hWndViewer
) hWndViewer
= hWndNext
;
1213 /**************************************************************************
1214 * IsClipboardFormatAvailable16 (USER.193)
1216 BOOL16 WINAPI
IsClipboardFormatAvailable16( UINT16 wFormat
)
1218 return IsClipboardFormatAvailable( wFormat
);
1222 /**************************************************************************
1223 * IsClipboardFormatAvailable (USER32.340)
1225 BOOL WINAPI
IsClipboardFormatAvailable( UINT wFormat
)
1229 if (wFormat
== 0) /* Reject this case quickly */
1232 /* If WINE is not the clipboard selection owner ask the clipboard driver */
1233 else if ( !USER_Driver
.pIsSelectionOwner() )
1234 bRet
= USER_Driver
.pIsClipboardFormatAvailable( (wFormat
== CF_TEXT
) ?
1235 CF_OEMTEXT
: wFormat
);
1236 /* Check if the format is in the local cache */
1238 bRet
= CLIPBOARD_IsPresent(wFormat
);
1240 TRACE("(%04X)- ret(%d)\n", wFormat
, bRet
);
1245 /**************************************************************************
1246 * GetOpenClipboardWindow16 (USER.248)
1247 * FIXME: This wont work if an external app owns the selection
1249 HWND16 WINAPI
GetOpenClipboardWindow16(void)
1252 return hWndClipWindow
;
1256 /**************************************************************************
1257 * GetOpenClipboardWindow (USER32.277)
1258 * FIXME: This wont work if an external app owns the selection
1260 HWND WINAPI
GetOpenClipboardWindow(void)
1263 return hWndClipWindow
;
1267 /**************************************************************************
1268 * GetPriorityClipboardFormat16 (USER.402)
1270 INT16 WINAPI
GetPriorityClipboardFormat16( UINT16
*lpPriorityList
, INT16 nCount
)
1272 FIXME("(%p,%d): stub\n", lpPriorityList
, nCount
);
1277 /**************************************************************************
1278 * GetPriorityClipboardFormat (USER32.279)
1280 INT WINAPI
GetPriorityClipboardFormat( UINT
*lpPriorityList
, INT nCount
)
1285 if(CountClipboardFormats() == 0)
1290 for(Counter
= 0; Counter
<= nCount
; Counter
++)
1292 if(IsClipboardFormatAvailable(*(lpPriorityList
+sizeof(INT
)*Counter
)))
1293 return *(lpPriorityList
+sizeof(INT
)*Counter
);