Fixed some issues found by winapi_check.
[wine/wine64.git] / windows / clipboard.c
blob3c3ddd881b8d72818969a22fe6d076bca8a0b0f6
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 "user.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 )
92 while(TRUE)
94 if (lpFormat == NULL ||
95 lpFormat->wFormatID == wID) break;
96 lpFormat = lpFormat->NextFormat;
98 return lpFormat;
101 LPWINE_CLIPFORMAT CLIPBOARD_LookupFormat( WORD wID )
103 return __lookup_format( ClipFormats, wID );
106 /**************************************************************************
107 * CLIPBOARD_IsLocked
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,
118 * or
119 * 2. if the caller is the clipboard owners task, AND is responding to a
120 * WM_RENDERFORMAT message.
122 if ( hClipLock == hTaskCur )
123 bIsLocked = FALSE;
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() );
135 if ( queue
136 && queue->smWaiting
137 && queue->smWaiting->msg == WM_RENDERFORMAT
138 && queue->smWaiting->hSrcQueue
140 bIsLocked = FALSE;
142 QUEUE_Unlock( queue );
145 return bIsLocked;
148 /**************************************************************************
149 * CLIPBOARD_ReleaseOwner
150 * Gives up ownership of the clipboard
152 void CLIPBOARD_ReleaseOwner()
154 hWndClipOwner = 0;
155 hTaskClipOwner = 0;
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
171 * more info on this.
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);
223 else
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;
263 while(lpFormat)
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)
277 /* special case */
279 if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
280 return ClipFormats[CF_TEXT-1].wDataPresent ||
281 ClipFormats[CF_OEMTEXT-1].wDataPresent;
282 else
284 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
285 if( lpFormat ) return (lpFormat->wDataPresent);
287 return FALSE;
290 /**************************************************************************
291 * CLIPBOARD_IsCacheRendered
292 * Checks if any data needs to be rendered to the clipboard cache
293 * RETURNS:
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 */
302 while(lpFormat)
304 if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
305 return FALSE;
307 lpFormat = lpFormat->NextFormat;
310 return TRUE;
314 /**************************************************************************
315 * CLIPBOARD_IsMemoryObject
316 * Tests if the clipboard format specifies a memory object
318 BOOL CLIPBOARD_IsMemoryObject( WORD wFormat )
320 switch(wFormat)
322 case CF_BITMAP:
323 case CF_METAFILEPICT:
324 case CF_DSPTEXT:
325 case CF_ENHMETAFILE:
326 case CF_HDROP:
327 case CF_PALETTE:
328 case CF_PENDATA:
329 return FALSE;
330 default:
331 return TRUE;
335 /***********************************************************************
336 * CLIPBOARD_GlobalDupMem( HGLOBAL )
337 * Helper method to duplicate an HGLOBAL chunk of memory into shared memory
339 HGLOBAL CLIPBOARD_GlobalDupMem( HGLOBAL hGlobalSrc )
341 HGLOBAL hGlobalDest;
342 PVOID pGlobalSrc, pGlobalDest;
343 DWORD cBytes;
345 if ( !hGlobalSrc )
346 return 0;
348 cBytes = GlobalSize(hGlobalSrc);
349 if ( 0 == cBytes )
350 return 0;
352 /* Turn on the DDESHARE and _MOVEABLE flags explicitly */
353 hGlobalDest = GlobalAlloc( GlobalFlags(hGlobalSrc) | GMEM_DDESHARE | GMEM_MOVEABLE,
354 cBytes );
355 if ( !hGlobalDest )
356 return 0;
358 pGlobalSrc = GlobalLock(hGlobalSrc);
359 pGlobalDest = GlobalLock(hGlobalDest);
360 if ( !pGlobalSrc || !pGlobalDest )
361 return 0;
363 memcpy(pGlobalDest, pGlobalSrc, cBytes);
365 GlobalUnlock(hGlobalSrc);
366 GlobalUnlock(hGlobalDest);
368 return 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 ) )
395 return FALSE;
398 * If Wine owns the clipboard, and the data is marked for delayed render,
399 * render it now.
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);
412 else
414 WARN("\thWndClipOwner (%04x) is lost!\n",
415 hWndClipOwner);
416 CLIPBOARD_ReleaseOwner();
417 lpFormat->wDataPresent = 0;
418 return FALSE;
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 */
461 else
463 lpSource = __lookup_format( ClipFormats, wFormat );
464 lpTarget = lpSource;
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 )
473 UINT16 size;
474 LPCSTR lpstrS;
475 LPSTR lpstrT;
477 if (lpSource->hData32)
479 size = GlobalSize( lpSource->hData32 );
480 lpstrS = (LPSTR)GlobalLock(lpSource->hData32);
482 else
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);
495 if( lpstrT )
497 if( lpSource->wFormatID == CF_TEXT )
498 CharToOemBuffA(lpstrS, lpstrT, size);
499 else
500 OemToCharBuffA(lpstrS, lpstrT, size);
501 TRACE("\tgot %s\n", lpstrT);
502 GlobalUnlock(lpTarget->hData32);
504 else
505 lpTarget->hData32 = 0;
507 /* Unlock source */
508 if (lpSource->hData32)
509 GlobalUnlock(lpSource->hData32);
510 else
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 )
537 BOOL bRet;
539 TRACE("(%04x)...\n", hWnd);
541 if (!hClipLock)
543 hClipLock = GetCurrentTask();
545 /* Save current user of the clipboard */
546 hWndClipWindow = hWnd;
547 bCBHasChanged = FALSE;
548 bRet = TRUE;
550 else bRet = FALSE;
552 TRACE(" returning %i\n", bRet);
553 return bRet;
557 /**************************************************************************
558 * CloseClipboard16 (USER.138)
560 BOOL16 WINAPI CloseClipboard16(void)
562 return CloseClipboard();
566 /**************************************************************************
567 * CloseClipboard (USER32.54)
569 BOOL WINAPI CloseClipboard(void)
571 TRACE("()\n");
573 if (hClipLock == GetCurrentTask())
575 hWndClipWindow = 0;
577 if (bCBHasChanged && hWndViewer)
578 SendMessage16(hWndViewer, WM_DRAWCLIPBOARD, 0, 0L);
579 hClipLock = 0;
581 return TRUE;
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)
600 TRACE("()\n");
602 if (hClipLock != GetCurrentTask())
604 WARN("Clipboard not opened by calling task!");
605 return FALSE;
608 /* destroy private objects */
610 if (hWndClipOwner)
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();
625 return TRUE;
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)
635 TRACE("()\n");
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)
646 TRACE("()\n");
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
664 * adding new data).
667 if( CLIPBOARD_IsLocked() || !lpFormat ||
668 (!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) )
670 WARN("Invalid hData or clipboard not opened by calling task!\n");
671 return 0;
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
717 * adding new data).
720 if( CLIPBOARD_IsLocked() || !lpFormat ||
721 (!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) )
723 WARN("Invalid hData or clipboard not opened by calling task!\n");
724 return 0;
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 );
759 else
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");
780 return 0;
783 if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
785 lpRender = CLIPBOARD_RenderText(wFormat);
786 if ( !lpRender ) return 0;
788 else
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) )
798 int size;
799 if( lpRender->wFormatID == CF_METAFILEPICT )
800 size = sizeof( METAFILEPICT16 );
801 else
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);
807 else
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) );
816 #endif
818 else
820 memcpy( GlobalLock16(lpRender->hData16),
821 GlobalLock(lpRender->hData32),
822 size );
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!");
847 return 0;
850 if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
852 lpRender = CLIPBOARD_RenderText(wFormat);
853 if ( !lpRender ) return 0;
855 else
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) )
865 int size;
866 if( lpRender->wFormatID == CF_METAFILEPICT )
867 size = sizeof( METAFILEPICT );
868 else
869 size = GlobalSize16(lpRender->hData16);
870 lpRender->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE,
871 size);
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) );
879 #endif
881 else
883 memcpy( GlobalLock(lpRender->hData32),
884 GlobalLock16(lpRender->hData16),
885 size );
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)
911 INT FormatCount = 0;
912 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
914 TRACE("()\n");
916 while(TRUE)
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));
934 FormatCount++;
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);
947 return 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;
966 BOOL bFormatPresent;
968 TRACE("(%04X)\n", wFormat);
970 if (CLIPBOARD_IsLocked())
972 WARN("Clipboard not opened by calling task!");
973 return 0;
976 if (wFormat == 0) /* start from the beginning */
977 lpFormat = ClipFormats;
978 else
980 /* walk up to the specified format record */
982 if( !(lpFormat = __lookup_format( lpFormat, wFormat )) )
983 return 0;
984 lpFormat = lpFormat->NextFormat; /* right */
987 while(TRUE)
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())
999 bFormatPresent =
1000 USER_Driver.pIsClipboardFormatAvailable( (lpFormat->wFormatID == CF_TEXT) ?
1001 CF_OEMTEXT : lpFormat->wFormatID );
1004 if (bFormatPresent)
1005 break;
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 */
1028 while(TRUE)
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!");
1046 return 0;
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);
1056 return 0;
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 );
1091 return ret;
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 )
1128 INT ret;
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 );
1134 if (maxlen > 0 && !MultiByteToWideChar( CP_ACP, 0, p, -1, retStr, maxlen ))
1135 retStr[maxlen-1] = 0;
1136 HeapFree( GetProcessHeap(), 0, p );
1137 return ret;
1141 /**************************************************************************
1142 * SetClipboardViewer16 (USER.147)
1144 HWND16 WINAPI SetClipboardViewer16( HWND16 hWnd )
1146 TRACE("(%04x)\n", hWnd);
1147 return SetClipboardViewer( hWnd );
1151 /**************************************************************************
1152 * SetClipboardViewer (USER32.471)
1154 HWND WINAPI SetClipboardViewer( HWND hWnd )
1156 HWND hwndPrev = hWndViewer;
1158 TRACE("(%04x): returning %04x\n", hWnd, hwndPrev);
1160 hWndViewer = hWnd;
1161 return hwndPrev;
1165 /**************************************************************************
1166 * GetClipboardViewer16 (USER.148)
1168 HWND16 WINAPI GetClipboardViewer16(void)
1170 TRACE("()\n");
1171 return hWndViewer;
1175 /**************************************************************************
1176 * GetClipboardViewer (USER32.226)
1178 HWND WINAPI GetClipboardViewer(void)
1180 TRACE("()\n");
1181 return hWndViewer;
1185 /**************************************************************************
1186 * ChangeClipboardChain16 (USER.149)
1188 BOOL16 WINAPI ChangeClipboardChain16(HWND16 hWnd, HWND16 hWndNext)
1190 return ChangeClipboardChain(hWnd, hWndNext);
1194 /**************************************************************************
1195 * ChangeClipboardChain (USER32.22)
1197 BOOL WINAPI ChangeClipboardChain(HWND hWnd, HWND hWndNext)
1199 BOOL bRet = 0;
1201 FIXME("(0x%04x, 0x%04x): stub?\n", hWnd, hWndNext);
1203 if( hWndViewer )
1204 bRet = !SendMessage16( hWndViewer, WM_CHANGECBCHAIN,
1205 (WPARAM16)hWnd, (LPARAM)hWndNext);
1206 else
1207 WARN("hWndViewer is lost\n");
1209 if( hWnd == hWndViewer ) hWndViewer = hWndNext;
1211 return bRet;
1215 /**************************************************************************
1216 * IsClipboardFormatAvailable16 (USER.193)
1218 BOOL16 WINAPI IsClipboardFormatAvailable16( UINT16 wFormat )
1220 return IsClipboardFormatAvailable( wFormat );
1224 /**************************************************************************
1225 * IsClipboardFormatAvailable (USER32.340)
1227 BOOL WINAPI IsClipboardFormatAvailable( UINT wFormat )
1229 BOOL bRet;
1231 if (wFormat == 0) /* Reject this case quickly */
1232 bRet = FALSE;
1234 /* If WINE is not the clipboard selection owner ask the clipboard driver */
1235 else if ( !USER_Driver.pIsSelectionOwner() )
1236 bRet = USER_Driver.pIsClipboardFormatAvailable( (wFormat == CF_TEXT) ?
1237 CF_OEMTEXT : wFormat );
1238 /* Check if the format is in the local cache */
1239 else
1240 bRet = CLIPBOARD_IsPresent(wFormat);
1242 TRACE("(%04X)- ret(%d)\n", wFormat, bRet);
1243 return bRet;
1247 /**************************************************************************
1248 * GetOpenClipboardWindow16 (USER.248)
1249 * FIXME: This wont work if an external app owns the selection
1251 HWND16 WINAPI GetOpenClipboardWindow16(void)
1253 TRACE("()\n");
1254 return hWndClipWindow;
1258 /**************************************************************************
1259 * GetOpenClipboardWindow (USER32.277)
1260 * FIXME: This wont work if an external app owns the selection
1262 HWND WINAPI GetOpenClipboardWindow(void)
1264 TRACE("()\n");
1265 return hWndClipWindow;
1269 /**************************************************************************
1270 * GetPriorityClipboardFormat16 (USER.402)
1272 INT16 WINAPI GetPriorityClipboardFormat16( UINT16 *lpPriorityList, INT16 nCount)
1274 FIXME("(%p,%d): stub\n", lpPriorityList, nCount );
1275 return 0;
1279 /**************************************************************************
1280 * GetPriorityClipboardFormat (USER32.279)
1282 INT WINAPI GetPriorityClipboardFormat( UINT *lpPriorityList, INT nCount )
1284 int Counter;
1285 TRACE("()\n");
1287 if(CountClipboardFormats() == 0)
1289 return 0;
1292 for(Counter = 0; Counter <= nCount; Counter++)
1294 if(IsClipboardFormatAvailable(*(lpPriorityList+sizeof(INT)*Counter)))
1295 return *(lpPriorityList+sizeof(INT)*Counter);
1298 return -1;
1302 /**************************************************************************
1303 * GetClipboardSequenceNumber (USER32)
1304 * Supported on Win2k/Win98
1305 * MSDN: Windows clipboard code keeps a serial number for the clipboard
1306 * for each window station. The number is incremented whenever the
1307 * contents change or are emptied.
1308 * If you do not have WINSTA_ACCESSCLIPBOARD then the function returns 0
1310 DWORD WINAPI GetClipboardSequenceNumber(VOID)
1312 FIXME("Returning 0, see windows/clipboard.c\n");
1313 /* FIXME: Use serial numbers */
1314 return 0;