Abey George (of Macadamian/Corel)
[wine.git] / windows / clipboard.c
blob62411b40e63771baa5ce1345f67b89c50b294b4d
1 /*
2 * WIN32 clipboard implementation
4 * Copyright 1994 Martin Ayotte
5 * 1996 Alex Korobka
6 * 1999 Noel Borthwick
8 * NOTES:
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)
16 * TODO:
20 #include <stdlib.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <fcntl.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include "windef.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29 #include "wine/winuser16.h"
30 #include "wine/winbase16.h"
31 #include "heap.h"
32 #include "message.h"
33 #include "task.h"
34 #include "queue.h"
35 #include "clipboard.h"
36 #include "debugtools.h"
38 DEFAULT_DEBUG_CHANNEL(clipboard)
40 #define CF_REGFORMATBASE 0xC000
42 /**************************************************************************
43 * Clipboard context global variables
46 CLIPBOARD_DRIVER *CLIPBOARD_Driver = NULL;
48 static HANDLE hClipLock = 0;
49 static BOOL bCBHasChanged = FALSE;
51 HWND hWndClipWindow = 0; /* window that last opened clipboard */
52 HWND hWndClipOwner = 0; /* current clipboard owner */
53 HANDLE16 hTaskClipOwner = 0; /* clipboard owner's task */
54 static HWND hWndViewer = 0; /* start of viewers chain */
56 static WORD LastRegFormat = CF_REGFORMATBASE;
58 /* Clipboard cache initial data.
59 * WARNING: This data ordering is dependendent on the WINE_CLIPFORMAT structure
60 * declared in clipboard.h
62 WINE_CLIPFORMAT ClipFormats[17] = {
63 { CF_TEXT, 1, 0, "Text", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, NULL, &ClipFormats[1]},
64 { CF_BITMAP, 1, 0, "Bitmap", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[0], &ClipFormats[2]},
65 { CF_METAFILEPICT, 1, 0, "MetaFile Picture", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[1], &ClipFormats[3]},
66 { CF_SYLK, 1, 0, "Sylk", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[2], &ClipFormats[4]},
67 { CF_DIF, 1, 0, "DIF", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[3], &ClipFormats[5]},
68 { CF_TIFF, 1, 0, "TIFF", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[4], &ClipFormats[6]},
69 { CF_OEMTEXT, 1, 0, "OEM Text", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[5], &ClipFormats[7]},
70 { CF_DIB, 1, 0, "DIB", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[6], &ClipFormats[8]},
71 { CF_PALETTE, 1, 0, "Palette", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[7], &ClipFormats[9]},
72 { CF_PENDATA, 1, 0, "PenData", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[8], &ClipFormats[10]},
73 { CF_RIFF, 1, 0, "RIFF", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[9], &ClipFormats[11]},
74 { CF_WAVE, 1, 0, "Wave", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[10], &ClipFormats[12]},
75 { CF_OWNERDISPLAY, 1, 0, "Owner Display", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[11], &ClipFormats[13]},
76 { CF_DSPTEXT, 1, 0, "DSPText", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[12], &ClipFormats[14]},
77 { CF_DSPMETAFILEPICT, 1, 0, "DSPMetaFile Picture", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[13], &ClipFormats[15]},
78 { CF_DSPBITMAP, 1, 0, "DSPBitmap", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[14], &ClipFormats[16]},
79 { CF_HDROP, 1, 0, "HDROP", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[15], NULL}
83 /**************************************************************************
84 * Internal Clipboard implementation methods
85 **************************************************************************/
88 /**************************************************************************
89 * CLIPBOARD_LookupFormat
91 static LPWINE_CLIPFORMAT __lookup_format( LPWINE_CLIPFORMAT lpFormat, WORD wID )
93 while(TRUE)
95 if (lpFormat == NULL ||
96 lpFormat->wFormatID == wID) break;
97 lpFormat = lpFormat->NextFormat;
99 return lpFormat;
102 LPWINE_CLIPFORMAT CLIPBOARD_LookupFormat( WORD wID )
104 return __lookup_format( ClipFormats, wID );
107 /**************************************************************************
108 * CLIPBOARD_IsLocked
109 * Check if the clipboard cache is available to the caller
111 BOOL CLIPBOARD_IsLocked()
113 BOOL bIsLocked = TRUE;
114 HANDLE16 hTaskCur = GetCurrentTask();
117 * The clipboard is available:
118 * 1. if the caller's task has opened the clipboard,
119 * or
120 * 2. if the caller is the clipboard owners task, AND is responding to a
121 * WM_RENDERFORMAT message.
123 if ( hClipLock == hTaskCur )
124 bIsLocked = FALSE;
126 else if ( hTaskCur == hTaskClipOwner )
128 /* Check if we're currently executing inside a window procedure
129 * called in response to a WM_RENDERFORMAT message. A WM_RENDERFORMAT
130 * handler is not permitted to open the clipboard since it has been opened
131 * by another client. However the handler must have access to the
132 * clipboard in order to update data in response to this message.
134 MESSAGEQUEUE *queue = QUEUE_Lock( GetFastQueue16() );
136 if ( queue
137 && queue->smWaiting
138 && queue->smWaiting->msg == WM_RENDERFORMAT
139 && queue->smWaiting->hSrcQueue
141 bIsLocked = FALSE;
143 QUEUE_Unlock( queue );
146 return bIsLocked;
149 /**************************************************************************
150 * CLIPBOARD_ReleaseOwner
151 * Gives up ownership of the clipboard
153 void CLIPBOARD_ReleaseOwner()
155 hWndClipOwner = 0;
156 hTaskClipOwner = 0;
159 /**************************************************************************
160 * CLIPBOARD_GlobalFreeProc
162 * This is a callback mechanism to allow HGLOBAL data to be released in
163 * the context of the process which allocated it. We post a WM_TIMER message
164 * to the owner window(in CLIPBOARD_DeleteRecord) and destroy the data(in idEvent)
165 * in this WndProc, which is invoked when the apps message loop calls DispatchMessage.
166 * This technique is discussed in Matt Pietrek's "Under the Hood".
167 * An article describing the same may be found in MSDN by searching for WM_TIMER.
168 * Note that this mechanism will probably stop working when WINE supports
169 * address space separation. When "queue events" are implemented in Wine we
170 * should switch to using that mechanism, since it is more robust and does not
171 * require a procedure address to be passed. See the SetWinEventHook API for
172 * more info on this.
174 VOID CALLBACK CLIPBOARD_GlobalFreeProc( HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime )
176 /* idEvent is the HGLOBAL to be deleted */
177 GlobalFree( (HGLOBAL)idEvent );
180 /**************************************************************************
181 * CLIPBOARD_DeleteRecord
183 void CLIPBOARD_DeleteRecord(LPWINE_CLIPFORMAT lpFormat, BOOL bChange)
185 if( (lpFormat->wFormatID >= CF_GDIOBJFIRST &&
186 lpFormat->wFormatID <= CF_GDIOBJLAST) || lpFormat->wFormatID == CF_BITMAP
187 || lpFormat->wFormatID == CF_PALETTE)
189 if (lpFormat->hData32)
190 DeleteObject(lpFormat->hData32);
191 if (lpFormat->hData16)
192 DeleteObject16(lpFormat->hData16);
194 else if( lpFormat->wFormatID == CF_METAFILEPICT )
196 if (lpFormat->hData32)
198 DeleteMetaFile( ((METAFILEPICT *)GlobalLock( lpFormat->hData32 ))->hMF );
199 PostMessageA(hWndClipOwner, WM_TIMER,
200 (WPARAM)lpFormat->hData32, (LPARAM)CLIPBOARD_GlobalFreeProc);
201 if (lpFormat->hDataSrc32)
203 /* Release lpFormat->hData32 in the context of the process which created it.
204 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
205 * GlobalFree(lpFormat->hDataSrc32);
207 PostMessageA(hWndClipOwner, WM_TIMER,
208 (WPARAM)lpFormat->hDataSrc32, (LPARAM)CLIPBOARD_GlobalFreeProc);
211 if (lpFormat->hData16)
212 /* HMETAFILE16 and HMETAFILE32 are apparently the same thing,
213 and a shallow copy is enough to share a METAFILEPICT
214 structure between 16bit and 32bit clipboards. The MetaFile
215 should of course only be deleted once. */
216 GlobalFree16(lpFormat->hData16);
218 if (lpFormat->hData16)
220 DeleteMetaFile16( ((METAFILEPICT16 *)GlobalLock16( lpFormat->hData16 ))->hMF );
221 GlobalFree16(lpFormat->hData16);
224 else
226 if (lpFormat->hData32)
228 /* Release lpFormat->hData32 in the context of the process which created it.
229 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
230 * GlobalFree( lpFormat->hData32 );
232 PostMessageA(hWndClipOwner, WM_TIMER,
233 (WPARAM)lpFormat->hData32, (LPARAM)CLIPBOARD_GlobalFreeProc);
235 if (lpFormat->hDataSrc32)
237 /* Release lpFormat->hData32 in the context of the process which created it.
238 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
239 * GlobalFree(lpFormat->hDataSrc32);
241 PostMessageA(hWndClipOwner, WM_TIMER,
242 (WPARAM)lpFormat->hDataSrc32, (LPARAM)CLIPBOARD_GlobalFreeProc);
244 if (lpFormat->hData16)
245 GlobalFree16(lpFormat->hData16);
248 lpFormat->wDataPresent = 0;
249 lpFormat->hData16 = 0;
250 lpFormat->hData32 = 0;
251 lpFormat->hDataSrc32 = 0;
252 lpFormat->drvData = 0;
254 if( bChange ) bCBHasChanged = TRUE;
257 /**************************************************************************
258 * CLIPBOARD_EmptyCache
260 void CLIPBOARD_EmptyCache( BOOL bChange )
262 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
264 while(lpFormat)
266 if ( lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32 )
267 CLIPBOARD_DeleteRecord( lpFormat, bChange );
269 lpFormat = lpFormat->NextFormat;
273 /**************************************************************************
274 * CLIPBOARD_IsPresent
276 BOOL CLIPBOARD_IsPresent(WORD wFormat)
278 /* special case */
280 if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
281 return ClipFormats[CF_TEXT-1].wDataPresent ||
282 ClipFormats[CF_OEMTEXT-1].wDataPresent;
283 else
285 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
286 if( lpFormat ) return (lpFormat->wDataPresent);
288 return FALSE;
291 /**************************************************************************
292 * CLIPBOARD_IsCacheRendered
293 * Checks if any data needs to be rendered to the clipboard cache
294 * RETURNS:
295 * TRUE - All clipboard data is available in the cache
296 * FALSE - Some data is marked for delayed render and needs rendering
298 BOOL CLIPBOARD_IsCacheRendered()
300 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
302 /* check if all formats were rendered */
303 while(lpFormat)
305 if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
306 return FALSE;
308 lpFormat = lpFormat->NextFormat;
311 return TRUE;
315 /**************************************************************************
316 * CLIPBOARD_IsMemoryObject
317 * Tests if the clipboard format specifies a memory object
319 BOOL CLIPBOARD_IsMemoryObject( WORD wFormat )
321 switch(wFormat)
323 case CF_BITMAP:
324 case CF_METAFILEPICT:
325 case CF_DSPTEXT:
326 case CF_ENHMETAFILE:
327 case CF_HDROP:
328 case CF_PALETTE:
329 case CF_PENDATA:
330 return FALSE;
331 default:
332 return TRUE;
336 /***********************************************************************
337 * CLIPBOARD_GlobalDupMem( HGLOBAL )
338 * Helper method to duplicate an HGLOBAL chunk of memory into shared memory
340 HGLOBAL CLIPBOARD_GlobalDupMem( HGLOBAL hGlobalSrc )
342 HGLOBAL hGlobalDest;
343 PVOID pGlobalSrc, pGlobalDest;
344 DWORD cBytes;
346 if ( !hGlobalSrc )
347 return 0;
349 cBytes = GlobalSize(hGlobalSrc);
350 if ( 0 == cBytes )
351 return 0;
353 /* Turn on the DDESHARE and _MOVEABLE flags explicitly */
354 hGlobalDest = GlobalAlloc( GlobalFlags(hGlobalSrc) | GMEM_DDESHARE | GMEM_MOVEABLE,
355 cBytes );
356 if ( !hGlobalDest )
357 return 0;
359 pGlobalSrc = GlobalLock(hGlobalSrc);
360 pGlobalDest = GlobalLock(hGlobalDest);
361 if ( !pGlobalSrc || !pGlobalDest )
362 return 0;
364 memcpy(pGlobalDest, pGlobalSrc, cBytes);
366 GlobalUnlock(hGlobalSrc);
367 GlobalUnlock(hGlobalDest);
369 return hGlobalDest;
372 /**************************************************************************
373 * CLIPBOARD_GetFormatName
374 * Gets the format name associated with an ID
376 char * CLIPBOARD_GetFormatName(UINT wFormat)
378 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
379 return (lpFormat) ? lpFormat->Name : NULL;
383 /**************************************************************************
384 * CLIPBOARD_RenderFormat
386 static BOOL CLIPBOARD_RenderFormat(LPWINE_CLIPFORMAT lpFormat)
389 * If WINE is not the selection owner, and the format is available
390 * we must ask the the driver to render the data to the clipboard cache.
392 if ( !CLIPBOARD_Driver->pIsSelectionOwner()
393 && CLIPBOARD_Driver->pIsFormatAvailable( lpFormat->wFormatID ) )
395 if ( !CLIPBOARD_Driver->pGetData( lpFormat->wFormatID ) )
396 return FALSE;
399 * If Wine owns the clipboard, and the data is marked for delayed render,
400 * render it now.
402 else if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
404 if( IsWindow(hWndClipOwner) )
406 /* Send a WM_RENDERFORMAT message to notify the owner to render the
407 * data requested into the clipboard.
409 TRACE("Sending WM_RENDERFORMAT message\n");
410 SendMessage16(hWndClipOwner,WM_RENDERFORMAT,
411 (WPARAM16)lpFormat->wFormatID,0L);
413 else
415 WARN("\thWndClipOwner (%04x) is lost!\n",
416 hWndClipOwner);
417 CLIPBOARD_ReleaseOwner();
418 lpFormat->wDataPresent = 0;
419 return FALSE;
423 return (lpFormat->hData16 || lpFormat->hData32) ? TRUE : FALSE;
427 /**************************************************************************
428 * CLIPBOARD_RenderText
430 * Renders text to the clipboard buffer converting between UNIX and DOS formats.
432 * RETURNS: pointer to the WINE_CLIPFORMAT if successful, NULL otherwise
434 * FIXME: Should be a pair of driver functions that convert between OEM text and Windows.
437 static LPWINE_CLIPFORMAT CLIPBOARD_RenderText( UINT wFormat )
439 LPWINE_CLIPFORMAT lpSource = ClipFormats;
440 LPWINE_CLIPFORMAT lpTarget;
442 /* Asked for CF_TEXT and not available - always attempt to convert from CF_OEM_TEXT */
443 if( wFormat == CF_TEXT && !ClipFormats[CF_TEXT-1].wDataPresent )
445 /* Convert OEMTEXT -> TEXT */
446 lpSource = &ClipFormats[CF_OEMTEXT-1];
447 lpTarget = &ClipFormats[CF_TEXT-1];
449 TRACE("\tOEMTEXT -> TEXT\n");
451 /* Asked for CF_OEM_TEXT, and CF_TEXT available */
452 else if( wFormat == CF_OEMTEXT && !ClipFormats[CF_OEMTEXT-1].wDataPresent
453 && ClipFormats[CF_TEXT-1].wDataPresent )
455 /* Convert TEXT -> OEMTEXT */
456 lpSource = &ClipFormats[CF_TEXT-1];
457 lpTarget = &ClipFormats[CF_OEMTEXT-1];
459 TRACE("\tTEXT -> OEMTEXT\n");
461 /* Text format requested is available - no conversion necessary */
462 else
464 lpSource = __lookup_format( ClipFormats, wFormat );
465 lpTarget = lpSource;
468 /* First render the source text format */
469 if ( !lpSource || !CLIPBOARD_RenderFormat(lpSource) ) return NULL;
471 /* Convert to the desired target text format, if necessary */
472 if( lpTarget != lpSource && !lpTarget->hData16 && !lpTarget->hData32 )
474 UINT16 size;
475 LPCSTR lpstrS;
476 LPSTR lpstrT;
478 if (lpSource->hData32)
480 size = GlobalSize( lpSource->hData32 );
481 lpstrS = (LPSTR)GlobalLock(lpSource->hData32);
483 else
485 size = GlobalSize16( lpSource->hData16 );
486 lpstrS = (LPSTR)GlobalLock16(lpSource->hData16);
489 if( !lpstrS ) return NULL;
490 TRACE("\tconverting from '%s' to '%s', %i chars\n",
491 lpSource->Name, lpTarget->Name, size);
493 lpTarget->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, size);
494 lpstrT = (LPSTR)GlobalLock(lpTarget->hData32);
496 if( lpstrT )
498 if( lpSource->wFormatID == CF_TEXT )
499 CharToOemBuffA(lpstrS, lpstrT, size);
500 else
501 OemToCharBuffA(lpstrS, lpstrT, size);
502 TRACE("\tgot %s\n", lpstrT);
503 GlobalUnlock(lpTarget->hData32);
505 else
506 lpTarget->hData32 = 0;
508 /* Unlock source */
509 if (lpSource->hData32)
510 GlobalUnlock(lpSource->hData32);
511 else
512 GlobalUnlock16(lpSource->hData16);
515 return (lpTarget->hData16 || lpTarget->hData32) ? lpTarget : NULL;
518 /**************************************************************************
519 * WIN32 Clipboard implementation
520 **************************************************************************/
522 /**************************************************************************
523 * OpenClipboard16 (USER.137)
525 BOOL16 WINAPI OpenClipboard16( HWND16 hWnd )
527 return OpenClipboard( hWnd );
531 /**************************************************************************
532 * OpenClipboard (USER32.407)
534 * Note: Netscape uses NULL hWnd to open the clipboard.
536 BOOL WINAPI OpenClipboard( HWND hWnd )
538 BOOL bRet;
540 TRACE("(%04x)...\n", hWnd);
542 if (!hClipLock)
544 hClipLock = GetCurrentTask();
546 /* Save current user of the clipboard */
547 hWndClipWindow = hWnd;
548 bCBHasChanged = FALSE;
549 bRet = TRUE;
551 else bRet = FALSE;
553 TRACE(" returning %i\n", bRet);
554 return bRet;
558 /**************************************************************************
559 * CloseClipboard16 (USER.138)
561 BOOL16 WINAPI CloseClipboard16(void)
563 return CloseClipboard();
567 /**************************************************************************
568 * CloseClipboard (USER32.54)
570 BOOL WINAPI CloseClipboard(void)
572 TRACE("()\n");
574 if (hClipLock == GetCurrentTask())
576 hWndClipWindow = 0;
578 if (bCBHasChanged && hWndViewer)
579 SendMessage16(hWndViewer, WM_DRAWCLIPBOARD, 0, 0L);
580 hClipLock = 0;
582 return TRUE;
586 /**************************************************************************
587 * EmptyClipboard16 (USER.139)
589 BOOL16 WINAPI EmptyClipboard16(void)
591 return EmptyClipboard();
595 /**************************************************************************
596 * EmptyClipboard (USER32.169)
597 * Empties and acquires ownership of the clipboard
599 BOOL WINAPI EmptyClipboard(void)
601 TRACE("()\n");
603 if (hClipLock != GetCurrentTask())
605 WARN("Clipboard not opened by calling task!");
606 return FALSE;
609 /* destroy private objects */
611 if (hWndClipOwner)
612 SendMessage16(hWndClipOwner, WM_DESTROYCLIPBOARD, 0, 0L);
614 /* empty the cache */
615 CLIPBOARD_EmptyCache(TRUE);
617 /* Assign ownership of the clipboard to the current client */
618 hWndClipOwner = hWndClipWindow;
620 /* Save the current task */
621 hTaskClipOwner = GetCurrentTask();
623 /* Tell the driver to acquire the selection */
624 CLIPBOARD_Driver->pAcquire();
626 return TRUE;
630 /**************************************************************************
631 * GetClipboardOwner16 (USER.140)
632 * FIXME: Can't return the owner if the clipbard is owned by an external app
634 HWND16 WINAPI GetClipboardOwner16(void)
636 TRACE("()\n");
637 return hWndClipOwner;
641 /**************************************************************************
642 * GetClipboardOwner (USER32.225)
643 * FIXME: Can't return the owner if the clipbard is owned by an external app
645 HWND WINAPI GetClipboardOwner(void)
647 TRACE("()\n");
648 return hWndClipOwner;
652 /**************************************************************************
653 * SetClipboardData16 (USER.141)
655 HANDLE16 WINAPI SetClipboardData16( UINT16 wFormat, HANDLE16 hData )
657 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
659 TRACE("(%04X, %04x) !\n", wFormat, hData);
661 /* NOTE: If the hData is zero and current owner doesn't match
662 * the window that opened the clipboard then this application
663 * is screwed because WM_RENDERFORMAT will go to the owner.
664 * (to become the owner it must call EmptyClipboard() before
665 * adding new data).
668 if( CLIPBOARD_IsLocked() || !lpFormat ||
669 (!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) )
671 WARN("Invalid hData or clipboard not opened by calling task!\n");
672 return 0;
675 /* Pass on the request to the driver */
676 CLIPBOARD_Driver->pSetData(wFormat);
678 if ( lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32 )
680 CLIPBOARD_DeleteRecord(lpFormat, TRUE);
682 /* delete existing CF_TEXT/CF_OEMTEXT aliases */
684 if( wFormat == CF_TEXT
685 && ( ClipFormats[CF_OEMTEXT-1].hData16
686 || ClipFormats[CF_OEMTEXT-1].hData32 )
687 && !ClipFormats[CF_OEMTEXT-1].wDataPresent )
688 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
689 if( wFormat == CF_OEMTEXT
690 && ( ClipFormats[CF_OEMTEXT-1].hData16
691 || ClipFormats[CF_OEMTEXT-1].hData32 )
692 && !ClipFormats[CF_TEXT-1].wDataPresent )
693 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
696 bCBHasChanged = TRUE;
697 lpFormat->wDataPresent = 1;
698 lpFormat->hData16 = hData; /* 0 is legal, see WM_RENDERFORMAT */
699 lpFormat->hData32 = 0;
701 return lpFormat->hData16;
705 /**************************************************************************
706 * SetClipboardData (USER32.470)
708 HANDLE WINAPI SetClipboardData( UINT wFormat, HANDLE hData )
710 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
712 TRACE("(%08X, %08x) !\n", wFormat, hData);
714 /* NOTE: If the hData is zero and current owner doesn't match
715 * the window that opened the clipboard then this application
716 * is screwed because WM_RENDERFORMAT will go to the owner.
717 * (to become the owner it must call EmptyClipboard() before
718 * adding new data).
721 if( CLIPBOARD_IsLocked() || !lpFormat ||
722 (!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) )
724 WARN("Invalid hData or clipboard not opened by calling task!\n");
725 return 0;
728 /* Tell the driver to acquire the selection */
729 CLIPBOARD_Driver->pAcquire();
731 if ( lpFormat->wDataPresent &&
732 (lpFormat->hData16 || lpFormat->hData32) )
734 CLIPBOARD_DeleteRecord(lpFormat, TRUE);
736 /* delete existing CF_TEXT/CF_OEMTEXT aliases */
738 if( wFormat == CF_TEXT
739 && ( ClipFormats[CF_OEMTEXT-1].hData16
740 || ClipFormats[CF_OEMTEXT-1].hData32 )
741 && !ClipFormats[CF_OEMTEXT-1].wDataPresent )
742 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
743 if( wFormat == CF_OEMTEXT
744 && ( ClipFormats[CF_OEMTEXT-1].hData16
745 || ClipFormats[CF_OEMTEXT-1].hData32 )
746 && !ClipFormats[CF_TEXT-1].wDataPresent )
747 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
750 bCBHasChanged = TRUE;
751 lpFormat->wDataPresent = 1;
752 lpFormat->hDataSrc32 = hData; /* Save the source handle */
755 * Make a shared duplicate if the memory is not shared
756 * TODO: What should be done for non-memory objects
758 if ( CLIPBOARD_IsMemoryObject(wFormat) && hData && !(GlobalFlags(hData) & GMEM_DDESHARE) )
759 lpFormat->hData32 = CLIPBOARD_GlobalDupMem( hData );
760 else
761 lpFormat->hData32 = hData; /* 0 is legal, see WM_RENDERFORMAT */
763 lpFormat->hData16 = 0;
765 return lpFormat->hData32; /* Should we return lpFormat->hDataSrc32 */
769 /**************************************************************************
770 * GetClipboardData16 (USER.142)
772 HANDLE16 WINAPI GetClipboardData16( UINT16 wFormat )
774 LPWINE_CLIPFORMAT lpRender = ClipFormats;
776 TRACE("(%04X)\n", wFormat);
778 if (CLIPBOARD_IsLocked())
780 WARN("Clipboard not opened by calling task!\n");
781 return 0;
784 if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
786 lpRender = CLIPBOARD_RenderText(wFormat);
787 if ( !lpRender ) return 0;
789 else
791 lpRender = __lookup_format( ClipFormats, wFormat );
792 if( !lpRender || !CLIPBOARD_RenderFormat(lpRender) ) return 0;
795 /* Convert between 32 -> 16 bit data, if necessary */
796 if( lpRender->hData32 && !lpRender->hData16
797 && CLIPBOARD_IsMemoryObject(wFormat) )
799 int size;
800 if( lpRender->wFormatID == CF_METAFILEPICT )
801 size = sizeof( METAFILEPICT16 );
802 else
803 size = GlobalSize(lpRender->hData32);
805 lpRender->hData16 = GlobalAlloc16(GMEM_ZEROINIT, size);
806 if( !lpRender->hData16 )
807 ERR("(%04X) -- not enough memory in 16b heap\n", wFormat);
808 else
810 if( lpRender->wFormatID == CF_METAFILEPICT )
812 FIXME("\timplement function CopyMetaFilePict32to16\n");
813 FIXME("\tin the appropriate file.\n");
814 #ifdef SOMEONE_IMPLEMENTED_ME
815 CopyMetaFilePict32to16( GlobalLock16(lpRender->hData16),
816 GlobalLock(lpRender->hData32) );
817 #endif
819 else
821 memcpy( GlobalLock16(lpRender->hData16),
822 GlobalLock(lpRender->hData32),
823 size );
825 GlobalUnlock16(lpRender->hData16);
826 GlobalUnlock(lpRender->hData32);
830 TRACE("\treturning %04x (type %i)\n",
831 lpRender->hData16, lpRender->wFormatID);
832 return lpRender->hData16;
836 /**************************************************************************
837 * GetClipboardData (USER32.222)
839 HANDLE WINAPI GetClipboardData( UINT wFormat )
841 LPWINE_CLIPFORMAT lpRender = ClipFormats;
843 TRACE("(%08X)\n", wFormat);
845 if (CLIPBOARD_IsLocked())
847 WARN("Clipboard not opened by calling task!");
848 return 0;
851 if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
853 lpRender = CLIPBOARD_RenderText(wFormat);
854 if ( !lpRender ) return 0;
856 else
858 lpRender = __lookup_format( ClipFormats, wFormat );
859 if( !lpRender || !CLIPBOARD_RenderFormat(lpRender) ) return 0;
862 /* Convert between 16 -> 32 bit data, if necessary */
863 if( lpRender->hData16 && !lpRender->hData32
864 && CLIPBOARD_IsMemoryObject(wFormat) )
866 int size;
867 if( lpRender->wFormatID == CF_METAFILEPICT )
868 size = sizeof( METAFILEPICT );
869 else
870 size = GlobalSize16(lpRender->hData16);
871 lpRender->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE,
872 size);
873 if( lpRender->wFormatID == CF_METAFILEPICT )
875 FIXME("\timplement function CopyMetaFilePict16to32\n");
876 FIXME("\tin the appropriate file.\n");
877 #ifdef SOMEONE_IMPLEMENTED_ME
878 CopyMetaFilePict16to32( GlobalLock16(lpRender->hData32),
879 GlobalLock(lpRender->hData16) );
880 #endif
882 else
884 memcpy( GlobalLock(lpRender->hData32),
885 GlobalLock16(lpRender->hData16),
886 size );
888 GlobalUnlock(lpRender->hData32);
889 GlobalUnlock16(lpRender->hData16);
892 TRACE("\treturning %04x (type %i)\n",
893 lpRender->hData32, lpRender->wFormatID);
894 return lpRender->hData32;
898 /**************************************************************************
899 * CountClipboardFormats16 (USER.143)
901 INT16 WINAPI CountClipboardFormats16(void)
903 return CountClipboardFormats();
907 /**************************************************************************
908 * CountClipboardFormats (USER32.63)
910 INT WINAPI CountClipboardFormats(void)
912 INT FormatCount = 0;
913 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
915 TRACE("()\n");
917 while(TRUE)
919 if (lpFormat == NULL) break;
921 if( lpFormat->wFormatID != CF_TEXT ) /* Don't count CF_TEXT */
924 * The format is available if either:
925 * 1. The data is already in the cache.
926 * 2. The selection is not owned by us(WINE) and the data is
927 * available to the clipboard driver.
929 if ( lpFormat->wDataPresent ||
930 ( !CLIPBOARD_Driver->pIsSelectionOwner()
931 && CLIPBOARD_Driver->pIsFormatAvailable( lpFormat->wFormatID ) ) )
933 TRACE("\tdata found for format 0x%04x(%s)\n",
934 lpFormat->wFormatID, CLIPBOARD_GetFormatName(lpFormat->wFormatID));
935 FormatCount++;
939 lpFormat = lpFormat->NextFormat;
942 /* these two are equivalent, adjust the total */
944 FormatCount += abs(ClipFormats[CF_TEXT-1].wDataPresent -
945 ClipFormats[CF_OEMTEXT-1].wDataPresent);
947 TRACE("\ttotal %d\n", FormatCount);
948 return FormatCount;
952 /**************************************************************************
953 * EnumClipboardFormats16 (USER.144)
955 UINT16 WINAPI EnumClipboardFormats16( UINT16 wFormat )
957 return EnumClipboardFormats( wFormat );
961 /**************************************************************************
962 * EnumClipboardFormats (USER32.179)
964 UINT WINAPI EnumClipboardFormats( UINT wFormat )
966 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
967 BOOL bFormatPresent;
969 TRACE("(%04X)\n", wFormat);
971 if (CLIPBOARD_IsLocked())
973 WARN("Clipboard not opened by calling task!");
974 return 0;
977 if (wFormat == 0) /* start from the beginning */
978 lpFormat = ClipFormats;
979 else
981 /* walk up to the specified format record */
983 if( !(lpFormat = __lookup_format( lpFormat, wFormat )) )
984 return 0;
985 lpFormat = lpFormat->NextFormat; /* right */
988 while(TRUE)
990 if (lpFormat == NULL) return 0;
992 /* Synthesize CF_TEXT from CF_OEMTEXT and vice versa */
993 bFormatPresent = (lpFormat->wDataPresent ||
994 (lpFormat->wFormatID == CF_OEMTEXT && ClipFormats[CF_TEXT-1].wDataPresent) ||
995 (lpFormat->wFormatID == CF_TEXT && ClipFormats[CF_OEMTEXT-1].wDataPresent) );
997 /* Query the driver if not yet in the cache */
998 if (!bFormatPresent && !CLIPBOARD_Driver->pIsSelectionOwner())
1000 bFormatPresent =
1001 CLIPBOARD_Driver->pIsFormatAvailable( (lpFormat->wFormatID == CF_TEXT) ?
1002 CF_OEMTEXT : lpFormat->wFormatID );
1005 if (bFormatPresent)
1006 break;
1008 lpFormat = lpFormat->NextFormat;
1011 return lpFormat->wFormatID;
1015 /**************************************************************************
1016 * RegisterClipboardFormat16 (USER.145)
1018 UINT16 WINAPI RegisterClipboardFormat16( LPCSTR FormatName )
1020 LPWINE_CLIPFORMAT lpNewFormat;
1021 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
1023 if (FormatName == NULL) return 0;
1025 TRACE("('%s') !\n", FormatName);
1027 /* walk format chain to see if it's already registered */
1029 while(TRUE)
1031 if ( !strcmp(lpFormat->Name,FormatName) )
1033 lpFormat->wRefCount++;
1034 return lpFormat->wFormatID;
1037 if ( lpFormat->NextFormat == NULL ) break;
1039 lpFormat = lpFormat->NextFormat;
1042 /* allocate storage for new format entry */
1044 lpNewFormat = (LPWINE_CLIPFORMAT)HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_CLIPFORMAT));
1045 if(lpNewFormat == NULL) {
1046 WARN("No more memory for a new format!");
1047 return 0;
1049 lpFormat->NextFormat = lpNewFormat;
1050 lpNewFormat->wFormatID = LastRegFormat;
1051 lpNewFormat->wRefCount = 1;
1053 lpNewFormat->Name = (LPSTR)HEAP_strdupA(GetProcessHeap(), 0, FormatName);
1054 if(lpNewFormat->Name == NULL) {
1055 WARN("No more memory for the new format name!");
1056 HeapFree(GetProcessHeap(), 0, lpNewFormat);
1057 return 0;
1060 lpNewFormat->wDataPresent = 0;
1061 lpNewFormat->hData16 = 0;
1062 lpNewFormat->hDataSrc32 = 0;
1063 lpNewFormat->hData32 = 0;
1064 lpNewFormat->drvData = 0;
1065 lpNewFormat->PrevFormat = lpFormat;
1066 lpNewFormat->NextFormat = NULL;
1068 /* Pass on the registration request to the driver */
1069 CLIPBOARD_Driver->pRegisterFormat( FormatName );
1071 return LastRegFormat++;
1075 /**************************************************************************
1076 * RegisterClipboardFormatA (USER32.431)
1078 UINT WINAPI RegisterClipboardFormatA( LPCSTR formatName )
1080 return RegisterClipboardFormat16( formatName );
1084 /**************************************************************************
1085 * RegisterClipboardFormatW (USER32.432)
1087 UINT WINAPI RegisterClipboardFormatW( LPCWSTR formatName )
1089 LPSTR aFormat = HEAP_strdupWtoA( GetProcessHeap(), 0, formatName );
1090 UINT ret = RegisterClipboardFormatA( aFormat );
1091 HeapFree( GetProcessHeap(), 0, aFormat );
1092 return ret;
1096 /**************************************************************************
1097 * GetClipboardFormatName16 (USER.146)
1099 INT16 WINAPI GetClipboardFormatName16( UINT16 wFormat, LPSTR retStr, INT16 maxlen )
1101 return GetClipboardFormatNameA( wFormat, retStr, maxlen );
1105 /**************************************************************************
1106 * GetClipboardFormatNameA (USER32.223)
1108 INT WINAPI GetClipboardFormatNameA( UINT wFormat, LPSTR retStr, INT maxlen )
1110 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
1112 TRACE("(%04X, %p, %d) !\n", wFormat, retStr, maxlen);
1114 if (lpFormat == NULL || lpFormat->Name == NULL ||
1115 lpFormat->wFormatID < CF_REGFORMATBASE) return 0;
1117 TRACE("Name='%s' !\n", lpFormat->Name);
1119 lstrcpynA( retStr, lpFormat->Name, maxlen );
1120 return strlen(retStr);
1124 /**************************************************************************
1125 * GetClipboardFormatNameW (USER32.224)
1127 INT WINAPI GetClipboardFormatNameW( UINT wFormat, LPWSTR retStr, INT maxlen )
1129 INT ret;
1130 LPSTR p = HeapAlloc( GetProcessHeap(), 0, maxlen );
1131 if(p == NULL) return 0; /* FIXME: is this the correct failure value? */
1133 ret = GetClipboardFormatNameA( wFormat, p, maxlen );
1134 lstrcpynAtoW( retStr, p, maxlen );
1135 HeapFree( GetProcessHeap(), 0, p );
1136 return ret;
1140 /**************************************************************************
1141 * SetClipboardViewer16 (USER.147)
1143 HWND16 WINAPI SetClipboardViewer16( HWND16 hWnd )
1145 TRACE("(%04x)\n", hWnd);
1146 return SetClipboardViewer( hWnd );
1150 /**************************************************************************
1151 * SetClipboardViewer (USER32.471)
1153 HWND WINAPI SetClipboardViewer( HWND hWnd )
1155 HWND hwndPrev = hWndViewer;
1157 TRACE("(%04x): returning %04x\n", hWnd, hwndPrev);
1159 hWndViewer = hWnd;
1160 return hwndPrev;
1164 /**************************************************************************
1165 * GetClipboardViewer16 (USER.148)
1167 HWND16 WINAPI GetClipboardViewer16(void)
1169 TRACE("()\n");
1170 return hWndViewer;
1174 /**************************************************************************
1175 * GetClipboardViewer (USER32.226)
1177 HWND WINAPI GetClipboardViewer(void)
1179 TRACE("()\n");
1180 return hWndViewer;
1184 /**************************************************************************
1185 * ChangeClipboardChain16 (USER.149)
1187 BOOL16 WINAPI ChangeClipboardChain16(HWND16 hWnd, HWND16 hWndNext)
1189 return ChangeClipboardChain(hWnd, hWndNext);
1193 /**************************************************************************
1194 * ChangeClipboardChain (USER32.22)
1196 BOOL WINAPI ChangeClipboardChain(HWND hWnd, HWND hWndNext)
1198 BOOL bRet = 0;
1200 FIXME("(0x%04x, 0x%04x): stub?\n", hWnd, hWndNext);
1202 if( hWndViewer )
1203 bRet = !SendMessage16( hWndViewer, WM_CHANGECBCHAIN,
1204 (WPARAM16)hWnd, (LPARAM)hWndNext);
1205 else
1206 WARN("hWndViewer is lost\n");
1208 if( hWnd == hWndViewer ) hWndViewer = hWndNext;
1210 return bRet;
1214 /**************************************************************************
1215 * IsClipboardFormatAvailable16 (USER.193)
1217 BOOL16 WINAPI IsClipboardFormatAvailable16( UINT16 wFormat )
1219 return IsClipboardFormatAvailable( wFormat );
1223 /**************************************************************************
1224 * IsClipboardFormatAvailable (USER32.340)
1226 BOOL WINAPI IsClipboardFormatAvailable( UINT wFormat )
1228 BOOL bRet;
1230 if (wFormat == 0) /* Reject this case quickly */
1231 bRet = FALSE;
1233 /* If WINE is not the clipboard selection owner ask the clipboard driver */
1234 else if ( !CLIPBOARD_Driver->pIsSelectionOwner() )
1235 bRet = CLIPBOARD_Driver->pIsFormatAvailable( (wFormat == CF_TEXT) ?
1236 CF_OEMTEXT : wFormat );
1237 /* Check if the format is in the local cache */
1238 else
1239 bRet = CLIPBOARD_IsPresent(wFormat);
1241 TRACE("(%04X)- ret(%d)\n", wFormat, bRet);
1242 return bRet;
1246 /**************************************************************************
1247 * GetOpenClipboardWindow16 (USER.248)
1248 * FIXME: This wont work if an external app owns the selection
1250 HWND16 WINAPI GetOpenClipboardWindow16(void)
1252 TRACE("()\n");
1253 return hWndClipWindow;
1257 /**************************************************************************
1258 * GetOpenClipboardWindow (USER32.277)
1259 * FIXME: This wont work if an external app owns the selection
1261 HWND WINAPI GetOpenClipboardWindow(void)
1263 TRACE("()\n");
1264 return hWndClipWindow;
1268 /**************************************************************************
1269 * GetPriorityClipboardFormat16 (USER.402)
1271 INT16 WINAPI GetPriorityClipboardFormat16( UINT16 *lpPriorityList, INT16 nCount)
1273 FIXME("(%p,%d): stub\n", lpPriorityList, nCount );
1274 return 0;
1278 /**************************************************************************
1279 * GetPriorityClipboardFormat (USER32.279)
1281 INT WINAPI GetPriorityClipboardFormat( UINT *lpPriorityList, INT nCount )
1283 int Counter;
1284 TRACE("()\n");
1286 if(CountClipboardFormats() == 0)
1288 return 0;
1291 for(Counter = 0; Counter <= nCount; Counter++)
1293 if(IsClipboardFormatAvailable(*(lpPriorityList+sizeof(INT)*Counter)))
1294 return *(lpPriorityList+sizeof(INT)*Counter);
1297 return -1;