Check that ci->hWindowMenu is not zero before using it.
[wine.git] / windows / clipboard.c
blob91540afd34d68066e6dab13d4373a567e86cf641
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 "xmalloc.h"
37 #include "debugtools.h"
39 DEFAULT_DEBUG_CHANNEL(clipboard)
41 #define CF_REGFORMATBASE 0xC000
43 /**************************************************************************
44 * Clipboard context global variables
47 CLIPBOARD_DRIVER *CLIPBOARD_Driver = NULL;
49 static HANDLE hClipLock = 0;
50 static BOOL bCBHasChanged = FALSE;
52 HWND hWndClipWindow = 0; /* window that last opened clipboard */
53 HWND hWndClipOwner = 0; /* current clipboard owner */
54 HANDLE16 hTaskClipOwner = 0; /* clipboard owner's task */
55 static HWND hWndViewer = 0; /* start of viewers chain */
57 static WORD LastRegFormat = CF_REGFORMATBASE;
59 /* Clipboard cache initial data.
60 * WARNING: This data ordering is dependendent on the WINE_CLIPFORMAT structure
61 * declared in clipboard.h
63 WINE_CLIPFORMAT ClipFormats[17] = {
64 { CF_TEXT, 1, 0, "Text", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, NULL, &ClipFormats[1]},
65 { CF_BITMAP, 1, 0, "Bitmap", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[0], &ClipFormats[2]},
66 { CF_METAFILEPICT, 1, 0, "MetaFile Picture", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[1], &ClipFormats[3]},
67 { CF_SYLK, 1, 0, "Sylk", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[2], &ClipFormats[4]},
68 { CF_DIF, 1, 0, "DIF", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[3], &ClipFormats[5]},
69 { CF_TIFF, 1, 0, "TIFF", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[4], &ClipFormats[6]},
70 { CF_OEMTEXT, 1, 0, "OEM Text", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[5], &ClipFormats[7]},
71 { CF_DIB, 1, 0, "DIB", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[6], &ClipFormats[8]},
72 { CF_PALETTE, 1, 0, "Palette", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[7], &ClipFormats[9]},
73 { CF_PENDATA, 1, 0, "PenData", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[8], &ClipFormats[10]},
74 { CF_RIFF, 1, 0, "RIFF", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[9], &ClipFormats[11]},
75 { CF_WAVE, 1, 0, "Wave", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[10], &ClipFormats[12]},
76 { CF_OWNERDISPLAY, 1, 0, "Owner Display", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[11], &ClipFormats[13]},
77 { CF_DSPTEXT, 1, 0, "DSPText", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[12], &ClipFormats[14]},
78 { CF_DSPMETAFILEPICT, 1, 0, "DSPMetaFile Picture", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[13], &ClipFormats[15]},
79 { CF_DSPBITMAP, 1, 0, "DSPBitmap", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[14], &ClipFormats[16]},
80 { CF_HDROP, 1, 0, "HDROP", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[15], NULL}
84 /**************************************************************************
85 * Internal Clipboard implementation methods
86 **************************************************************************/
89 /**************************************************************************
90 * CLIPBOARD_LookupFormat
92 static LPWINE_CLIPFORMAT __lookup_format( LPWINE_CLIPFORMAT lpFormat, WORD wID )
94 while(TRUE)
96 if (lpFormat == NULL ||
97 lpFormat->wFormatID == wID) break;
98 lpFormat = lpFormat->NextFormat;
100 return lpFormat;
103 LPWINE_CLIPFORMAT CLIPBOARD_LookupFormat( WORD wID )
105 return __lookup_format( ClipFormats, wID );
108 /**************************************************************************
109 * CLIPBOARD_IsLocked
110 * Check if the clipboard cache is available to the caller
112 BOOL CLIPBOARD_IsLocked()
114 BOOL bIsLocked = TRUE;
115 HANDLE16 hTaskCur = GetCurrentTask();
118 * The clipboard is available:
119 * 1. if the caller's task has opened the clipboard,
120 * or
121 * 2. if the caller is the clipboard owners task, AND is responding to a
122 * WM_RENDERFORMAT message.
124 if ( hClipLock == hTaskCur )
125 bIsLocked = FALSE;
127 else if ( hTaskCur == hTaskClipOwner )
129 /* Check if we're currently executing inside a window procedure
130 * called in response to a WM_RENDERFORMAT message. A WM_RENDERFORMAT
131 * handler is not permitted to open the clipboard since it has been opened
132 * by another client. However the handler must have access to the
133 * clipboard in order to update data in response to this message.
135 MESSAGEQUEUE *queue = QUEUE_Lock( GetFastQueue16() );
137 if ( queue
138 && queue->smWaiting
139 && queue->smWaiting->msg == WM_RENDERFORMAT
140 && queue->smWaiting->hSrcQueue
142 bIsLocked = FALSE;
144 QUEUE_Unlock( queue );
147 return bIsLocked;
150 /**************************************************************************
151 * CLIPBOARD_ReleaseOwner
152 * Gives up ownership of the clipboard
154 void CLIPBOARD_ReleaseOwner()
156 hWndClipOwner = 0;
157 hTaskClipOwner = 0;
160 /**************************************************************************
161 * CLIPBOARD_GlobalFreeProc
163 * This is a callback mechanism to allow HGLOBAL data to be released in
164 * the context of the process which allocated it. We post a WM_TIMER message
165 * to the owner window(in CLIPBOARD_DeleteRecord) and destroy the data(in idEvent)
166 * in this WndProc, which is invoked when the apps message loop calls DispatchMessage.
167 * This technique is discussed in Matt Pietrek's "Under the Hood".
168 * An article describing the same may be found in MSDN by searching for WM_TIMER.
169 * Note that this mechanism will probably stop working when WINE supports
170 * address space separation. When "queue events" are implemented in Wine we
171 * should switch to using that mechanism, since it is more robust and does not
172 * require a procedure address to be passed. See the SetWinEventHook API for
173 * more info on this.
175 VOID CALLBACK CLIPBOARD_GlobalFreeProc( HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime )
177 /* idEvent is the HGLOBAL to be deleted */
178 GlobalFree( (HGLOBAL)idEvent );
181 /**************************************************************************
182 * CLIPBOARD_DeleteRecord
184 void CLIPBOARD_DeleteRecord(LPWINE_CLIPFORMAT lpFormat, BOOL bChange)
186 if( (lpFormat->wFormatID >= CF_GDIOBJFIRST &&
187 lpFormat->wFormatID <= CF_GDIOBJLAST) || lpFormat->wFormatID == CF_BITMAP
188 || lpFormat->wFormatID == CF_PALETTE)
190 if (lpFormat->hData32)
191 DeleteObject(lpFormat->hData32);
192 if (lpFormat->hData16)
193 DeleteObject16(lpFormat->hData16);
195 else if( lpFormat->wFormatID == CF_METAFILEPICT )
197 if (lpFormat->hData32)
199 DeleteMetaFile( ((METAFILEPICT *)GlobalLock( lpFormat->hData32 ))->hMF );
200 PostMessageA(hWndClipOwner, WM_TIMER,
201 (WPARAM)lpFormat->hData32, (LPARAM)CLIPBOARD_GlobalFreeProc);
202 if (lpFormat->hDataSrc32)
204 /* Release lpFormat->hData32 in the context of the process which created it.
205 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
206 * GlobalFree(lpFormat->hDataSrc32);
208 PostMessageA(hWndClipOwner, WM_TIMER,
209 (WPARAM)lpFormat->hDataSrc32, (LPARAM)CLIPBOARD_GlobalFreeProc);
212 if (lpFormat->hData16)
213 /* HMETAFILE16 and HMETAFILE32 are apparently the same thing,
214 and a shallow copy is enough to share a METAFILEPICT
215 structure between 16bit and 32bit clipboards. The MetaFile
216 should of course only be deleted once. */
217 GlobalFree16(lpFormat->hData16);
219 if (lpFormat->hData16)
221 DeleteMetaFile16( ((METAFILEPICT16 *)GlobalLock16( lpFormat->hData16 ))->hMF );
222 GlobalFree16(lpFormat->hData16);
225 else
227 if (lpFormat->hData32)
229 /* Release lpFormat->hData32 in the context of the process which created it.
230 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
231 * GlobalFree( lpFormat->hData32 );
233 PostMessageA(hWndClipOwner, WM_TIMER,
234 (WPARAM)lpFormat->hData32, (LPARAM)CLIPBOARD_GlobalFreeProc);
236 if (lpFormat->hDataSrc32)
238 /* Release lpFormat->hData32 in the context of the process which created it.
239 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
240 * GlobalFree(lpFormat->hDataSrc32);
242 PostMessageA(hWndClipOwner, WM_TIMER,
243 (WPARAM)lpFormat->hDataSrc32, (LPARAM)CLIPBOARD_GlobalFreeProc);
245 if (lpFormat->hData16)
246 GlobalFree16(lpFormat->hData16);
249 lpFormat->wDataPresent = 0;
250 lpFormat->hData16 = 0;
251 lpFormat->hData32 = 0;
252 lpFormat->hDataSrc32 = 0;
253 lpFormat->drvData = 0;
255 if( bChange ) bCBHasChanged = TRUE;
258 /**************************************************************************
259 * CLIPBOARD_EmptyCache
261 void CLIPBOARD_EmptyCache( BOOL bChange )
263 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
265 while(lpFormat)
267 if ( lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32 )
268 CLIPBOARD_DeleteRecord( lpFormat, bChange );
270 lpFormat = lpFormat->NextFormat;
274 /**************************************************************************
275 * CLIPBOARD_IsPresent
277 BOOL CLIPBOARD_IsPresent(WORD wFormat)
279 /* special case */
281 if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
282 return ClipFormats[CF_TEXT-1].wDataPresent ||
283 ClipFormats[CF_OEMTEXT-1].wDataPresent;
284 else
286 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
287 if( lpFormat ) return (lpFormat->wDataPresent);
289 return FALSE;
292 /**************************************************************************
293 * CLIPBOARD_IsCacheRendered
294 * Checks if any data needs to be rendered to the clipboard cache
295 * RETURNS:
296 * TRUE - All clipboard data is available in the cache
297 * FALSE - Some data is marked for delayed render and needs rendering
299 BOOL CLIPBOARD_IsCacheRendered()
301 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
303 /* check if all formats were rendered */
304 while(lpFormat)
306 if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
307 return FALSE;
309 lpFormat = lpFormat->NextFormat;
312 return TRUE;
316 /**************************************************************************
317 * CLIPBOARD_IsMemoryObject
318 * Tests if the clipboard format specifies a memory object
320 BOOL CLIPBOARD_IsMemoryObject( WORD wFormat )
322 switch(wFormat)
324 case CF_BITMAP:
325 case CF_METAFILEPICT:
326 case CF_DSPTEXT:
327 case CF_ENHMETAFILE:
328 case CF_HDROP:
329 case CF_PALETTE:
330 case CF_PENDATA:
331 return FALSE;
332 default:
333 return TRUE;
337 /***********************************************************************
338 * CLIPBOARD_GlobalDupMem( HGLOBAL )
339 * Helper method to duplicate an HGLOBAL chunk of memory into shared memory
341 HGLOBAL CLIPBOARD_GlobalDupMem( HGLOBAL hGlobalSrc )
343 HGLOBAL hGlobalDest;
344 PVOID pGlobalSrc, pGlobalDest;
345 DWORD cBytes;
347 if ( !hGlobalSrc )
348 return 0;
350 cBytes = GlobalSize(hGlobalSrc);
351 if ( 0 == cBytes )
352 return 0;
354 /* Turn on the DDESHARE and _MOVEABLE flags explicitly */
355 hGlobalDest = GlobalAlloc( GlobalFlags(hGlobalSrc) | GMEM_DDESHARE | GMEM_MOVEABLE,
356 cBytes );
357 if ( !hGlobalDest )
358 return 0;
360 pGlobalSrc = GlobalLock(hGlobalSrc);
361 pGlobalDest = GlobalLock(hGlobalDest);
362 if ( !pGlobalSrc || !pGlobalDest )
363 return 0;
365 memcpy(pGlobalDest, pGlobalSrc, cBytes);
367 GlobalUnlock(hGlobalSrc);
368 GlobalUnlock(hGlobalDest);
370 return hGlobalDest;
373 /**************************************************************************
374 * CLIPBOARD_GetFormatName
375 * Gets the format name associated with an ID
377 char * CLIPBOARD_GetFormatName(UINT wFormat)
379 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
380 return (lpFormat) ? lpFormat->Name : NULL;
384 /**************************************************************************
385 * CLIPBOARD_RenderFormat
387 static BOOL CLIPBOARD_RenderFormat(LPWINE_CLIPFORMAT lpFormat)
390 * If WINE is not the selection owner, and the format is available
391 * we must ask the the driver to render the data to the clipboard cache.
393 if ( !CLIPBOARD_Driver->pIsSelectionOwner()
394 && CLIPBOARD_Driver->pIsFormatAvailable( lpFormat->wFormatID ) )
396 if ( !CLIPBOARD_Driver->pGetData( lpFormat->wFormatID ) )
397 return FALSE;
400 * If Wine owns the clipboard, and the data is marked for delayed render,
401 * render it now.
403 else if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
405 if( IsWindow(hWndClipOwner) )
407 /* Send a WM_RENDERFORMAT message to notify the owner to render the
408 * data requested into the clipboard.
410 TRACE("Sending WM_RENDERFORMAT message\n");
411 SendMessage16(hWndClipOwner,WM_RENDERFORMAT,
412 (WPARAM16)lpFormat->wFormatID,0L);
414 else
416 WARN("\thWndClipOwner (%04x) is lost!\n",
417 hWndClipOwner);
418 CLIPBOARD_ReleaseOwner();
419 lpFormat->wDataPresent = 0;
420 return FALSE;
424 return (lpFormat->hData16 || lpFormat->hData32) ? TRUE : FALSE;
428 /**************************************************************************
429 * CLIPBOARD_RenderText
431 * Renders text to the clipboard buffer converting between UNIX and DOS formats.
433 * RETURNS: pointer to the WINE_CLIPFORMAT if successful, NULL otherwise
435 * FIXME: Should be a pair of driver functions that convert between OEM text and Windows.
438 static LPWINE_CLIPFORMAT CLIPBOARD_RenderText( UINT wFormat )
440 LPWINE_CLIPFORMAT lpSource = ClipFormats;
441 LPWINE_CLIPFORMAT lpTarget;
443 /* Asked for CF_TEXT and not available - always attempt to convert from CF_OEM_TEXT */
444 if( wFormat == CF_TEXT && !ClipFormats[CF_TEXT-1].wDataPresent )
446 /* Convert OEMTEXT -> TEXT */
447 lpSource = &ClipFormats[CF_OEMTEXT-1];
448 lpTarget = &ClipFormats[CF_TEXT-1];
450 TRACE("\tOEMTEXT -> TEXT\n");
452 /* Asked for CF_OEM_TEXT, and CF_TEXT available */
453 else if( wFormat == CF_OEMTEXT && !ClipFormats[CF_OEMTEXT-1].wDataPresent
454 && ClipFormats[CF_TEXT-1].wDataPresent )
456 /* Convert TEXT -> OEMTEXT */
457 lpSource = &ClipFormats[CF_TEXT-1];
458 lpTarget = &ClipFormats[CF_OEMTEXT-1];
460 TRACE("\tTEXT -> OEMTEXT\n");
462 /* Text format requested is available - no conversion necessary */
463 else
465 lpSource = __lookup_format( ClipFormats, wFormat );
466 lpTarget = lpSource;
469 /* First render the source text format */
470 if ( !lpSource || !CLIPBOARD_RenderFormat(lpSource) ) return NULL;
472 /* Convert to the desired target text format, if necessary */
473 if( lpTarget != lpSource && !lpTarget->hData16 && !lpTarget->hData32 )
475 UINT16 size;
476 LPCSTR lpstrS;
477 LPSTR lpstrT;
479 if (lpSource->hData32)
481 size = GlobalSize( lpSource->hData32 );
482 lpstrS = (LPSTR)GlobalLock(lpSource->hData32);
484 else
486 size = GlobalSize16( lpSource->hData16 );
487 lpstrS = (LPSTR)GlobalLock16(lpSource->hData16);
490 if( !lpstrS ) return NULL;
491 TRACE("\tconverting from '%s' to '%s', %i chars\n",
492 lpSource->Name, lpTarget->Name, size);
494 lpTarget->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, size);
495 lpstrT = (LPSTR)GlobalLock(lpTarget->hData32);
497 if( lpstrT )
499 if( lpSource->wFormatID == CF_TEXT )
500 CharToOemBuffA(lpstrS, lpstrT, size);
501 else
502 OemToCharBuffA(lpstrS, lpstrT, size);
503 TRACE("\tgot %s\n", lpstrT);
504 GlobalUnlock(lpTarget->hData32);
506 else
507 lpTarget->hData32 = 0;
509 /* Unlock source */
510 if (lpSource->hData32)
511 GlobalUnlock(lpSource->hData32);
512 else
513 GlobalUnlock16(lpSource->hData16);
516 return (lpTarget->hData16 || lpTarget->hData32) ? lpTarget : NULL;
519 /**************************************************************************
520 * WIN32 Clipboard implementation
521 **************************************************************************/
523 /**************************************************************************
524 * OpenClipboard16 (USER.137)
526 BOOL16 WINAPI OpenClipboard16( HWND16 hWnd )
528 return OpenClipboard( hWnd );
532 /**************************************************************************
533 * OpenClipboard32 (USER32.407)
535 * Note: Netscape uses NULL hWnd to open the clipboard.
537 BOOL WINAPI OpenClipboard( HWND hWnd )
539 BOOL bRet;
541 TRACE("(%04x)...\n", hWnd);
543 if (!hClipLock)
545 hClipLock = GetCurrentTask();
547 /* Save current user of the clipboard */
548 hWndClipWindow = hWnd;
549 bCBHasChanged = FALSE;
550 bRet = TRUE;
552 else bRet = FALSE;
554 TRACE(" returning %i\n", bRet);
555 return bRet;
559 /**************************************************************************
560 * CloseClipboard16 (USER.138)
562 BOOL16 WINAPI CloseClipboard16(void)
564 return CloseClipboard();
568 /**************************************************************************
569 * CloseClipboard32 (USER32.54)
571 BOOL WINAPI CloseClipboard(void)
573 TRACE("()\n");
575 if (hClipLock == GetCurrentTask())
577 hWndClipWindow = 0;
579 if (bCBHasChanged && hWndViewer)
580 SendMessage16(hWndViewer, WM_DRAWCLIPBOARD, 0, 0L);
581 hClipLock = 0;
583 return TRUE;
587 /**************************************************************************
588 * EmptyClipboard16 (USER.139)
590 BOOL16 WINAPI EmptyClipboard16(void)
592 return EmptyClipboard();
596 /**************************************************************************
597 * EmptyClipboard32 (USER32.169)
598 * Empties and acquires ownership of the clipboard
600 BOOL WINAPI EmptyClipboard(void)
602 TRACE("()\n");
604 if (hClipLock != GetCurrentTask())
606 WARN("Clipboard not opened by calling task!");
607 return FALSE;
610 /* destroy private objects */
612 if (hWndClipOwner)
613 SendMessage16(hWndClipOwner, WM_DESTROYCLIPBOARD, 0, 0L);
615 /* empty the cache */
616 CLIPBOARD_EmptyCache(TRUE);
618 /* Assign ownership of the clipboard to the current client */
619 hWndClipOwner = hWndClipWindow;
621 /* Save the current task */
622 hTaskClipOwner = GetCurrentTask();
624 /* Tell the driver to acquire the selection */
625 CLIPBOARD_Driver->pAcquire();
627 return TRUE;
631 /**************************************************************************
632 * GetClipboardOwner16 (USER.140)
633 * FIXME: Can't return the owner if the clipbard is owned by an external app
635 HWND16 WINAPI GetClipboardOwner16(void)
637 TRACE("()\n");
638 return hWndClipOwner;
642 /**************************************************************************
643 * GetClipboardOwner32 (USER32.225)
644 * FIXME: Can't return the owner if the clipbard is owned by an external app
646 HWND WINAPI GetClipboardOwner(void)
648 TRACE("()\n");
649 return hWndClipOwner;
653 /**************************************************************************
654 * SetClipboardData16 (USER.141)
656 HANDLE16 WINAPI SetClipboardData16( UINT16 wFormat, HANDLE16 hData )
658 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
660 TRACE("(%04X, %04x) !\n", wFormat, hData);
662 /* NOTE: If the hData is zero and current owner doesn't match
663 * the window that opened the clipboard then this application
664 * is screwed because WM_RENDERFORMAT will go to the owner.
665 * (to become the owner it must call EmptyClipboard() before
666 * adding new data).
669 if( CLIPBOARD_IsLocked() || !lpFormat ||
670 (!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) )
672 WARN("Invalid hData or clipboard not opened by calling task!\n");
673 return 0;
676 /* Pass on the request to the driver */
677 CLIPBOARD_Driver->pSetData(wFormat);
679 if ( lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32 )
681 CLIPBOARD_DeleteRecord(lpFormat, TRUE);
683 /* delete existing CF_TEXT/CF_OEMTEXT aliases */
685 if( wFormat == CF_TEXT
686 && ( ClipFormats[CF_OEMTEXT-1].hData16
687 || ClipFormats[CF_OEMTEXT-1].hData32 )
688 && !ClipFormats[CF_OEMTEXT-1].wDataPresent )
689 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
690 if( wFormat == CF_OEMTEXT
691 && ( ClipFormats[CF_OEMTEXT-1].hData16
692 || ClipFormats[CF_OEMTEXT-1].hData32 )
693 && !ClipFormats[CF_TEXT-1].wDataPresent )
694 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
697 bCBHasChanged = TRUE;
698 lpFormat->wDataPresent = 1;
699 lpFormat->hData16 = hData; /* 0 is legal, see WM_RENDERFORMAT */
700 lpFormat->hData32 = 0;
702 return lpFormat->hData16;
706 /**************************************************************************
707 * SetClipboardData (USER32.470)
709 HANDLE WINAPI SetClipboardData( UINT wFormat, HANDLE hData )
711 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
713 TRACE("(%08X, %08x) !\n", wFormat, hData);
715 /* NOTE: If the hData is zero and current owner doesn't match
716 * the window that opened the clipboard then this application
717 * is screwed because WM_RENDERFORMAT will go to the owner.
718 * (to become the owner it must call EmptyClipboard() before
719 * adding new data).
722 if( CLIPBOARD_IsLocked() || !lpFormat ||
723 (!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) )
725 WARN("Invalid hData or clipboard not opened by calling task!\n");
726 return 0;
729 /* Tell the driver to acquire the selection */
730 CLIPBOARD_Driver->pAcquire();
732 if ( lpFormat->wDataPresent &&
733 (lpFormat->hData16 || lpFormat->hData32) )
735 CLIPBOARD_DeleteRecord(lpFormat, TRUE);
737 /* delete existing CF_TEXT/CF_OEMTEXT aliases */
739 if( wFormat == CF_TEXT
740 && ( ClipFormats[CF_OEMTEXT-1].hData16
741 || ClipFormats[CF_OEMTEXT-1].hData32 )
742 && !ClipFormats[CF_OEMTEXT-1].wDataPresent )
743 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
744 if( wFormat == CF_OEMTEXT
745 && ( ClipFormats[CF_OEMTEXT-1].hData16
746 || ClipFormats[CF_OEMTEXT-1].hData32 )
747 && !ClipFormats[CF_TEXT-1].wDataPresent )
748 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
751 bCBHasChanged = TRUE;
752 lpFormat->wDataPresent = 1;
753 lpFormat->hDataSrc32 = hData; /* Save the source handle */
756 * Make a shared duplicate if the memory is not shared
757 * TODO: What should be done for non-memory objects
759 if ( CLIPBOARD_IsMemoryObject(wFormat) && hData && !(GlobalFlags(hData) & GMEM_DDESHARE) )
760 lpFormat->hData32 = CLIPBOARD_GlobalDupMem( hData );
761 else
762 lpFormat->hData32 = hData; /* 0 is legal, see WM_RENDERFORMAT */
764 lpFormat->hData16 = 0;
766 return lpFormat->hData32; /* Should we return lpFormat->hDataSrc32 */
770 /**************************************************************************
771 * GetClipboardData16 (USER.142)
773 HANDLE16 WINAPI GetClipboardData16( UINT16 wFormat )
775 LPWINE_CLIPFORMAT lpRender = ClipFormats;
777 TRACE("(%04X)\n", wFormat);
779 if (CLIPBOARD_IsLocked())
781 WARN("Clipboard not opened by calling task!\n");
782 return 0;
785 if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
787 lpRender = CLIPBOARD_RenderText(wFormat);
788 if ( !lpRender ) return 0;
790 else
792 lpRender = __lookup_format( ClipFormats, wFormat );
793 if( !lpRender || !CLIPBOARD_RenderFormat(lpRender) ) return 0;
796 /* Convert between 32 -> 16 bit data, if necessary */
797 if( lpRender->hData32 && !lpRender->hData16
798 && CLIPBOARD_IsMemoryObject(wFormat) )
800 int size;
801 if( lpRender->wFormatID == CF_METAFILEPICT )
802 size = sizeof( METAFILEPICT16 );
803 else
804 size = GlobalSize(lpRender->hData32);
806 lpRender->hData16 = GlobalAlloc16(GMEM_ZEROINIT, size);
807 if( !lpRender->hData16 )
808 ERR("(%04X) -- not enough memory in 16b heap\n", wFormat);
809 else
811 if( lpRender->wFormatID == CF_METAFILEPICT )
813 FIXME("\timplement function CopyMetaFilePict32to16\n");
814 FIXME("\tin the appropriate file.\n");
815 #ifdef SOMEONE_IMPLEMENTED_ME
816 CopyMetaFilePict32to16( GlobalLock16(lpRender->hData16),
817 GlobalLock(lpRender->hData32) );
818 #endif
820 else
822 memcpy( GlobalLock16(lpRender->hData16),
823 GlobalLock(lpRender->hData32),
824 size );
826 GlobalUnlock16(lpRender->hData16);
827 GlobalUnlock(lpRender->hData32);
831 TRACE("\treturning %04x (type %i)\n",
832 lpRender->hData16, lpRender->wFormatID);
833 return lpRender->hData16;
837 /**************************************************************************
838 * GetClipboardData32 (USER32.222)
840 HANDLE WINAPI GetClipboardData( UINT wFormat )
842 LPWINE_CLIPFORMAT lpRender = ClipFormats;
844 TRACE("(%08X)\n", wFormat);
846 if (CLIPBOARD_IsLocked())
848 WARN("Clipboard not opened by calling task!");
849 return 0;
852 if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
854 lpRender = CLIPBOARD_RenderText(wFormat);
855 if ( !lpRender ) return 0;
857 else
859 lpRender = __lookup_format( ClipFormats, wFormat );
860 if( !lpRender || !CLIPBOARD_RenderFormat(lpRender) ) return 0;
863 /* Convert between 16 -> 32 bit data, if necessary */
864 if( lpRender->hData16 && !lpRender->hData32
865 && CLIPBOARD_IsMemoryObject(wFormat) )
867 int size;
868 if( lpRender->wFormatID == CF_METAFILEPICT )
869 size = sizeof( METAFILEPICT );
870 else
871 size = GlobalSize16(lpRender->hData16);
872 lpRender->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE,
873 size);
874 if( lpRender->wFormatID == CF_METAFILEPICT )
876 FIXME("\timplement function CopyMetaFilePict16to32\n");
877 FIXME("\tin the appropriate file.\n");
878 #ifdef SOMEONE_IMPLEMENTED_ME
879 CopyMetaFilePict16to32( GlobalLock16(lpRender->hData32),
880 GlobalLock(lpRender->hData16) );
881 #endif
883 else
885 memcpy( GlobalLock(lpRender->hData32),
886 GlobalLock16(lpRender->hData16),
887 size );
889 GlobalUnlock(lpRender->hData32);
890 GlobalUnlock16(lpRender->hData16);
893 TRACE("\treturning %04x (type %i)\n",
894 lpRender->hData32, lpRender->wFormatID);
895 return lpRender->hData32;
899 /**************************************************************************
900 * CountClipboardFormats16 (USER.143)
902 INT16 WINAPI CountClipboardFormats16(void)
904 return CountClipboardFormats();
908 /**************************************************************************
909 * CountClipboardFormats32 (USER32.63)
911 INT WINAPI CountClipboardFormats(void)
913 INT FormatCount = 0;
914 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
916 TRACE("()\n");
918 while(TRUE)
920 if (lpFormat == NULL) break;
922 if( lpFormat->wFormatID != CF_TEXT ) /* Don't count CF_TEXT */
925 * The format is available if either:
926 * 1. The data is already in the cache.
927 * 2. The selection is not owned by us(WINE) and the data is
928 * available to the clipboard driver.
930 if ( lpFormat->wDataPresent ||
931 ( !CLIPBOARD_Driver->pIsSelectionOwner()
932 && CLIPBOARD_Driver->pIsFormatAvailable( lpFormat->wFormatID ) ) )
934 TRACE("\tdata found for format 0x%04x(%s)\n",
935 lpFormat->wFormatID, CLIPBOARD_GetFormatName(lpFormat->wFormatID));
936 FormatCount++;
940 lpFormat = lpFormat->NextFormat;
943 /* these two are equivalent, adjust the total */
945 FormatCount += abs(ClipFormats[CF_TEXT-1].wDataPresent -
946 ClipFormats[CF_OEMTEXT-1].wDataPresent);
948 TRACE("\ttotal %d\n", FormatCount);
949 return FormatCount;
953 /**************************************************************************
954 * EnumClipboardFormats16 (USER.144)
956 UINT16 WINAPI EnumClipboardFormats16( UINT16 wFormat )
958 return EnumClipboardFormats( wFormat );
962 /**************************************************************************
963 * EnumClipboardFormats32 (USER32.179)
965 UINT WINAPI EnumClipboardFormats( UINT wFormat )
967 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
968 BOOL bFormatPresent;
970 TRACE("(%04X)\n", wFormat);
972 if (CLIPBOARD_IsLocked())
974 WARN("Clipboard not opened by calling task!");
975 return 0;
978 if (wFormat == 0) /* start from the beginning */
979 lpFormat = ClipFormats;
980 else
982 /* walk up to the specified format record */
984 if( !(lpFormat = __lookup_format( lpFormat, wFormat )) )
985 return 0;
986 lpFormat = lpFormat->NextFormat; /* right */
989 while(TRUE)
991 if (lpFormat == NULL) return 0;
993 /* Synthesize CF_TEXT from CF_OEMTEXT and vice versa */
994 bFormatPresent = (lpFormat->wDataPresent ||
995 (lpFormat->wFormatID == CF_OEMTEXT && ClipFormats[CF_TEXT-1].wDataPresent) ||
996 (lpFormat->wFormatID == CF_TEXT && ClipFormats[CF_OEMTEXT-1].wDataPresent) );
998 /* Query the driver if not yet in the cache */
999 if (!bFormatPresent && !CLIPBOARD_Driver->pIsSelectionOwner())
1001 bFormatPresent =
1002 CLIPBOARD_Driver->pIsFormatAvailable( (lpFormat->wFormatID == CF_TEXT) ?
1003 CF_OEMTEXT : lpFormat->wFormatID );
1006 if (bFormatPresent)
1007 break;
1009 lpFormat = lpFormat->NextFormat;
1012 return lpFormat->wFormatID;
1016 /**************************************************************************
1017 * RegisterClipboardFormat16 (USER.145)
1019 UINT16 WINAPI RegisterClipboardFormat16( LPCSTR FormatName )
1021 LPWINE_CLIPFORMAT lpNewFormat;
1022 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
1024 if (FormatName == NULL) return 0;
1026 TRACE("('%s') !\n", FormatName);
1028 /* walk format chain to see if it's already registered */
1030 while(TRUE)
1032 if ( !strcmp(lpFormat->Name,FormatName) )
1034 lpFormat->wRefCount++;
1035 return lpFormat->wFormatID;
1038 if ( lpFormat->NextFormat == NULL ) break;
1040 lpFormat = lpFormat->NextFormat;
1043 /* allocate storage for new format entry */
1045 lpNewFormat = (LPWINE_CLIPFORMAT)xmalloc(sizeof(WINE_CLIPFORMAT));
1046 lpFormat->NextFormat = lpNewFormat;
1047 lpNewFormat->wFormatID = LastRegFormat;
1048 lpNewFormat->wRefCount = 1;
1050 lpNewFormat->Name = (LPSTR)xmalloc(strlen(FormatName) + 1);
1051 strcpy(lpNewFormat->Name, FormatName);
1053 lpNewFormat->wDataPresent = 0;
1054 lpNewFormat->hData16 = 0;
1055 lpNewFormat->hDataSrc32 = 0;
1056 lpNewFormat->hData32 = 0;
1057 lpNewFormat->drvData = 0;
1058 lpNewFormat->PrevFormat = lpFormat;
1059 lpNewFormat->NextFormat = NULL;
1061 /* Pass on the registration request to the driver */
1062 CLIPBOARD_Driver->pRegisterFormat( FormatName );
1064 return LastRegFormat++;
1068 /**************************************************************************
1069 * RegisterClipboardFormat32A (USER32.431)
1071 UINT WINAPI RegisterClipboardFormatA( LPCSTR formatName )
1073 return RegisterClipboardFormat16( formatName );
1077 /**************************************************************************
1078 * RegisterClipboardFormat32W (USER32.432)
1080 UINT WINAPI RegisterClipboardFormatW( LPCWSTR formatName )
1082 LPSTR aFormat = HEAP_strdupWtoA( GetProcessHeap(), 0, formatName );
1083 UINT ret = RegisterClipboardFormatA( aFormat );
1084 HeapFree( GetProcessHeap(), 0, aFormat );
1085 return ret;
1089 /**************************************************************************
1090 * GetClipboardFormatName16 (USER.146)
1092 INT16 WINAPI GetClipboardFormatName16( UINT16 wFormat, LPSTR retStr, INT16 maxlen )
1094 return GetClipboardFormatNameA( wFormat, retStr, maxlen );
1098 /**************************************************************************
1099 * GetClipboardFormatName32A (USER32.223)
1101 INT WINAPI GetClipboardFormatNameA( UINT wFormat, LPSTR retStr, INT maxlen )
1103 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
1105 TRACE("(%04X, %p, %d) !\n", wFormat, retStr, maxlen);
1107 if (lpFormat == NULL || lpFormat->Name == NULL ||
1108 lpFormat->wFormatID < CF_REGFORMATBASE) return 0;
1110 TRACE("Name='%s' !\n", lpFormat->Name);
1112 lstrcpynA( retStr, lpFormat->Name, maxlen );
1113 return strlen(retStr);
1117 /**************************************************************************
1118 * GetClipboardFormatName32W (USER32.224)
1120 INT WINAPI GetClipboardFormatNameW( UINT wFormat, LPWSTR retStr, INT maxlen )
1122 LPSTR p = HEAP_xalloc( GetProcessHeap(), 0, maxlen );
1123 INT ret = GetClipboardFormatNameA( wFormat, p, maxlen );
1124 lstrcpynAtoW( retStr, p, maxlen );
1125 HeapFree( GetProcessHeap(), 0, p );
1126 return ret;
1130 /**************************************************************************
1131 * SetClipboardViewer16 (USER.147)
1133 HWND16 WINAPI SetClipboardViewer16( HWND16 hWnd )
1135 TRACE("(%04x)\n", hWnd);
1136 return SetClipboardViewer( hWnd );
1140 /**************************************************************************
1141 * SetClipboardViewer32 (USER32.471)
1143 HWND WINAPI SetClipboardViewer( HWND hWnd )
1145 HWND hwndPrev = hWndViewer;
1147 TRACE("(%04x): returning %04x\n", hWnd, hwndPrev);
1149 hWndViewer = hWnd;
1150 return hwndPrev;
1154 /**************************************************************************
1155 * GetClipboardViewer16 (USER.148)
1157 HWND16 WINAPI GetClipboardViewer16(void)
1159 TRACE("()\n");
1160 return hWndViewer;
1164 /**************************************************************************
1165 * GetClipboardViewer32 (USER32.226)
1167 HWND WINAPI GetClipboardViewer(void)
1169 TRACE("()\n");
1170 return hWndViewer;
1174 /**************************************************************************
1175 * ChangeClipboardChain16 (USER.149)
1177 BOOL16 WINAPI ChangeClipboardChain16(HWND16 hWnd, HWND16 hWndNext)
1179 return ChangeClipboardChain(hWnd, hWndNext);
1183 /**************************************************************************
1184 * ChangeClipboardChain32 (USER32.22)
1186 BOOL WINAPI ChangeClipboardChain(HWND hWnd, HWND hWndNext)
1188 BOOL bRet = 0;
1190 FIXME("(0x%04x, 0x%04x): stub?\n", hWnd, hWndNext);
1192 if( hWndViewer )
1193 bRet = !SendMessage16( hWndViewer, WM_CHANGECBCHAIN,
1194 (WPARAM16)hWnd, (LPARAM)hWndNext);
1195 else
1196 WARN("hWndViewer is lost\n");
1198 if( hWnd == hWndViewer ) hWndViewer = hWndNext;
1200 return bRet;
1204 /**************************************************************************
1205 * IsClipboardFormatAvailable16 (USER.193)
1207 BOOL16 WINAPI IsClipboardFormatAvailable16( UINT16 wFormat )
1209 return IsClipboardFormatAvailable( wFormat );
1213 /**************************************************************************
1214 * IsClipboardFormatAvailable32 (USER32.340)
1216 BOOL WINAPI IsClipboardFormatAvailable( UINT wFormat )
1218 BOOL bRet;
1220 if (wFormat == 0) /* Reject this case quickly */
1221 bRet = FALSE;
1223 /* If WINE is not the clipboard selection owner ask the clipboard driver */
1224 else if ( !CLIPBOARD_Driver->pIsSelectionOwner() )
1225 bRet = CLIPBOARD_Driver->pIsFormatAvailable( (wFormat == CF_TEXT) ?
1226 CF_OEMTEXT : wFormat );
1227 /* Check if the format is in the local cache */
1228 else
1229 bRet = CLIPBOARD_IsPresent(wFormat);
1231 TRACE("(%04X)- ret(%d)\n", wFormat, bRet);
1232 return bRet;
1236 /**************************************************************************
1237 * GetOpenClipboardWindow16 (USER.248)
1238 * FIXME: This wont work if an external app owns the selection
1240 HWND16 WINAPI GetOpenClipboardWindow16(void)
1242 TRACE("()\n");
1243 return hWndClipWindow;
1247 /**************************************************************************
1248 * GetOpenClipboardWindow32 (USER32.277)
1249 * FIXME: This wont work if an external app owns the selection
1251 HWND WINAPI GetOpenClipboardWindow(void)
1253 TRACE("()\n");
1254 return hWndClipWindow;
1258 /**************************************************************************
1259 * GetPriorityClipboardFormat16 (USER.402)
1261 INT16 WINAPI GetPriorityClipboardFormat16( UINT16 *lpPriorityList, INT16 nCount)
1263 FIXME("(%p,%d): stub\n", lpPriorityList, nCount );
1264 return 0;
1268 /**************************************************************************
1269 * GetPriorityClipboardFormat32 (USER32.279)
1271 INT WINAPI GetPriorityClipboardFormat( UINT *lpPriorityList, INT nCount )
1273 int Counter;
1274 TRACE("()\n");
1276 if(CountClipboardFormats() == 0)
1278 return 0;
1281 for(Counter = 0; Counter <= nCount; Counter++)
1283 if(IsClipboardFormatAvailable(*(lpPriorityList+sizeof(INT)*Counter)))
1284 return *(lpPriorityList+sizeof(INT)*Counter);
1287 return -1;