Remove duplicate definition of _tmain.
[wine.git] / windows / clipboard.c
blobfc969cd3b116409070f0fab2f5c51c1fd72d1adc
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)
17 #include <stdlib.h>
18 #include <sys/types.h>
19 #include <fcntl.h>
20 #include <unistd.h>
21 #include <string.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wingdi.h"
26 #include "winuser.h"
27 #include "wine/winuser16.h"
28 #include "wine/winbase16.h"
29 #include "heap.h"
30 #include "user.h"
31 #include "win.h"
32 #include "clipboard.h"
33 #include "debugtools.h"
35 DEFAULT_DEBUG_CHANNEL(clipboard);
37 #define CF_REGFORMATBASE 0xC000
39 /**************************************************************************
40 * Clipboard context global variables
43 static HANDLE hClipLock = 0;
44 static BOOL bCBHasChanged = FALSE;
46 static HWND hWndClipWindow; /* window that last opened clipboard */
47 static HWND hWndClipOwner; /* current clipboard owner */
48 static HANDLE16 hTaskClipOwner; /* clipboard owner's task */
49 static HWND hWndViewer; /* start of viewers chain */
51 static WORD LastRegFormat = CF_REGFORMATBASE;
53 /* Clipboard cache initial data.
54 * WARNING: This data ordering is dependent on the WINE_CLIPFORMAT structure
55 * declared in clipboard.h
57 WINE_CLIPFORMAT ClipFormats[] = {
58 { CF_TEXT, 1, 0, "Text", 0, 0, 0, 0, NULL, &ClipFormats[1]},
59 { CF_BITMAP, 1, 0, "Bitmap", 0, 0, 0, 0, &ClipFormats[0], &ClipFormats[2]},
60 { CF_METAFILEPICT, 1, 0, "MetaFile Picture", 0, 0, 0, 0, &ClipFormats[1], &ClipFormats[3]},
61 { CF_SYLK, 1, 0, "Sylk", 0, 0, 0, 0, &ClipFormats[2], &ClipFormats[4]},
62 { CF_DIF, 1, 0, "DIF", 0, 0, 0, 0, &ClipFormats[3], &ClipFormats[5]},
63 { CF_TIFF, 1, 0, "TIFF", 0, 0, 0, 0, &ClipFormats[4], &ClipFormats[6]},
64 { CF_OEMTEXT, 1, 0, "OEM Text", 0, 0, 0, 0, &ClipFormats[5], &ClipFormats[7]},
65 { CF_DIB, 1, 0, "DIB", 0, 0, 0, 0, &ClipFormats[6], &ClipFormats[8]},
66 { CF_PALETTE, 1, 0, "Palette", 0, 0, 0, 0, &ClipFormats[7], &ClipFormats[9]},
67 { CF_PENDATA, 1, 0, "PenData", 0, 0, 0, 0, &ClipFormats[8], &ClipFormats[10]},
68 { CF_RIFF, 1, 0, "RIFF", 0, 0, 0, 0, &ClipFormats[9], &ClipFormats[11]},
69 { CF_WAVE, 1, 0, "Wave", 0, 0, 0, 0, &ClipFormats[10], &ClipFormats[12]},
70 { CF_UNICODETEXT, 1, 0, "Unicode Text", 0, 0, 0, 0, &ClipFormats[11], &ClipFormats[13]},
71 { CF_OWNERDISPLAY, 1, 0, "Owner Display", 0, 0, 0, 0, &ClipFormats[12], &ClipFormats[14]},
72 { CF_DSPTEXT, 1, 0, "DSPText", 0, 0, 0, 0, &ClipFormats[13], &ClipFormats[15]},
73 { CF_DSPMETAFILEPICT, 1, 0, "DSPMetaFile Picture", 0, 0, 0, 0, &ClipFormats[14], &ClipFormats[16]},
74 { CF_DSPBITMAP, 1, 0, "DSPBitmap", 0, 0, 0, 0, &ClipFormats[15], &ClipFormats[17]},
75 { CF_HDROP, 1, 0, "HDROP", 0, 0, 0, 0, &ClipFormats[16], NULL}
79 /**************************************************************************
80 * Internal Clipboard implementation methods
81 **************************************************************************/
84 /**************************************************************************
85 * CLIPBOARD_LookupFormat
87 static LPWINE_CLIPFORMAT __lookup_format( LPWINE_CLIPFORMAT lpFormat, WORD wID )
89 while(TRUE)
91 if (lpFormat == NULL ||
92 lpFormat->wFormatID == wID) break;
93 lpFormat = lpFormat->NextFormat;
95 return lpFormat;
98 LPWINE_CLIPFORMAT CLIPBOARD_LookupFormat( WORD wID )
100 return __lookup_format( ClipFormats, wID );
103 /**************************************************************************
104 * CLIPBOARD_IsLocked
105 * Check if the clipboard cache is available to the caller
107 BOOL CLIPBOARD_IsLocked()
109 BOOL bIsLocked = TRUE;
110 HANDLE16 hTaskCur = GetCurrentTask();
113 * The clipboard is available:
114 * 1. if the caller's task has opened the clipboard,
115 * or
116 * 2. if the caller is the clipboard owners task, AND is responding to a
117 * WM_RENDERFORMAT message.
119 if ( hClipLock == hTaskCur )
120 bIsLocked = FALSE;
122 else if ( hTaskCur == hTaskClipOwner )
124 /* Check if we're currently executing inside a window procedure
125 * called in response to a WM_RENDERFORMAT message. A WM_RENDERFORMAT
126 * handler is not permitted to open the clipboard since it has been opened
127 * by another client. However the handler must have access to the
128 * clipboard in order to update data in response to this message.
130 #if 0
131 MESSAGEQUEUE *queue = QUEUE_Current();
133 if ( queue
134 && queue->smWaiting
135 && queue->smWaiting->msg == WM_RENDERFORMAT
136 && queue->smWaiting->hSrcQueue
138 bIsLocked = FALSE;
139 #else
140 /* FIXME: queue check no longer possible */
141 bIsLocked = FALSE;
142 #endif
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 || wFormat == CF_UNICODETEXT )
280 return ClipFormats[CF_TEXT-1].wDataPresent ||
281 ClipFormats[CF_OEMTEXT-1].wDataPresent ||
282 ClipFormats[CF_UNICODETEXT-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 driver to render the data to the clipboard cache.
392 TRACE("enter format=%d\n", lpFormat->wFormatID);
393 if ( !USER_Driver.pIsSelectionOwner()
394 && USER_Driver.pIsClipboardFormatAvailable( lpFormat->wFormatID ) )
396 if ( !USER_Driver.pGetClipboardData( 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 SendMessageW( hWndClipOwner, WM_RENDERFORMAT, (WPARAM)lpFormat->wFormatID, 0 );
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;
426 /**************************************************************************
427 * CLIPBOARD_ConvertText
428 * Returns number of required/converted characters - not bytes!
430 static INT CLIPBOARD_ConvertText(WORD src_fmt, void const *src, INT src_size,
431 WORD dst_fmt, void *dst, INT dst_size)
433 UINT cp;
435 if(src_fmt == CF_UNICODETEXT)
437 switch(dst_fmt)
439 case CF_TEXT:
440 cp = CP_ACP;
441 break;
442 case CF_OEMTEXT:
443 cp = CP_OEMCP;
444 break;
445 default:
446 return 0;
448 return WideCharToMultiByte(cp, 0, src, src_size, dst, dst_size, NULL, NULL);
451 if(dst_fmt == CF_UNICODETEXT)
453 switch(src_fmt)
455 case CF_TEXT:
456 cp = CP_ACP;
457 break;
458 case CF_OEMTEXT:
459 cp = CP_OEMCP;
460 break;
461 default:
462 return 0;
464 return MultiByteToWideChar(cp, 0, src, src_size, dst, dst_size);
467 if(!dst_size) return src_size;
469 if(dst_size > src_size) dst_size = src_size;
471 if(src_fmt == CF_TEXT )
472 CharToOemBuffA(src, dst, dst_size);
473 else
474 OemToCharBuffA(src, dst, dst_size);
476 return dst_size;
479 /**************************************************************************
480 * CLIPBOARD_RenderText
482 * Renders text to the clipboard buffer converting between UNIX and DOS formats.
484 * RETURNS: pointer to the WINE_CLIPFORMAT if successful, NULL otherwise
486 * FIXME: Should be a pair of driver functions that convert between OEM text and Windows.
489 static LPWINE_CLIPFORMAT CLIPBOARD_RenderText( UINT wFormat )
491 LPWINE_CLIPFORMAT lpSource = ClipFormats;
492 LPWINE_CLIPFORMAT lpTarget = NULL;
493 BOOL foundData = FALSE;
495 /* Asked for CF_TEXT */
496 if( wFormat == CF_TEXT)
498 if(ClipFormats[CF_TEXT-1].wDataPresent)
500 lpSource = &ClipFormats[CF_TEXT-1];
501 lpTarget = &ClipFormats[CF_TEXT-1];
502 foundData = TRUE;
503 TRACE("\t TEXT -> TEXT\n");
505 else if(ClipFormats[CF_UNICODETEXT-1].wDataPresent)
507 /* Convert UNICODETEXT -> TEXT */
508 lpSource = &ClipFormats[CF_UNICODETEXT-1];
509 lpTarget = &ClipFormats[CF_TEXT-1];
510 foundData = TRUE;
511 TRACE("\tUNICODETEXT -> TEXT\n");
513 else if(ClipFormats[CF_OEMTEXT-1].wDataPresent)
515 /* Convert OEMTEXT -> TEXT */
516 lpSource = &ClipFormats[CF_OEMTEXT-1];
517 lpTarget = &ClipFormats[CF_TEXT-1];
518 foundData = TRUE;
519 TRACE("\tOEMTEXT -> TEXT\n");
522 /* Asked for CF_OEMTEXT */
523 else if( wFormat == CF_OEMTEXT)
525 if(ClipFormats[CF_OEMTEXT-1].wDataPresent)
527 lpSource = &ClipFormats[CF_OEMTEXT-1];
528 lpTarget = &ClipFormats[CF_OEMTEXT-1];
529 foundData = TRUE;
530 TRACE("\tOEMTEXT -> OEMTEXT\n");
532 else if(ClipFormats[CF_UNICODETEXT-1].wDataPresent)
534 /* Convert UNICODETEXT -> OEMTEXT */
535 lpSource = &ClipFormats[CF_UNICODETEXT-1];
536 lpTarget = &ClipFormats[CF_OEMTEXT-1];
537 foundData = TRUE;
538 TRACE("\tUNICODETEXT -> OEMTEXT\n");
540 else if(ClipFormats[CF_TEXT-1].wDataPresent)
542 /* Convert TEXT -> OEMTEXT */
543 lpSource = &ClipFormats[CF_TEXT-1];
544 lpTarget = &ClipFormats[CF_OEMTEXT-1];
545 foundData = TRUE;
546 TRACE("\tTEXT -> OEMTEXT\n");
549 /* Asked for CF_UNICODETEXT */
550 else if( wFormat == CF_UNICODETEXT )
552 if(ClipFormats[CF_UNICODETEXT-1].wDataPresent)
554 lpSource = &ClipFormats[CF_UNICODETEXT-1];
555 lpTarget = &ClipFormats[CF_UNICODETEXT-1];
556 foundData = TRUE;
557 TRACE("\tUNICODETEXT -> UNICODETEXT\n");
559 else if(ClipFormats[CF_TEXT-1].wDataPresent)
561 /* Convert TEXT -> UNICODETEXT */
562 lpSource = &ClipFormats[CF_TEXT-1];
563 lpTarget = &ClipFormats[CF_UNICODETEXT-1];
564 foundData = TRUE;
565 TRACE("\tTEXT -> UNICODETEXT\n");
567 else if(ClipFormats[CF_OEMTEXT-1].wDataPresent)
569 /* Convert OEMTEXT -> UNICODETEXT */
570 lpSource = &ClipFormats[CF_OEMTEXT-1];
571 lpTarget = &ClipFormats[CF_UNICODETEXT-1];
572 foundData = TRUE;
573 TRACE("\tOEMTEXT -> UNICODETEXT\n");
576 if (!foundData)
578 if ((wFormat == CF_TEXT) || (wFormat == CF_OEMTEXT))
580 lpSource = &ClipFormats[CF_UNICODETEXT-1];
581 lpTarget = __lookup_format( ClipFormats, wFormat );
583 else
585 lpSource = __lookup_format( ClipFormats, wFormat );
586 lpTarget = lpSource;
590 /* First render the source text format */
591 if ( !lpSource || !CLIPBOARD_RenderFormat(lpSource) ) return NULL;
593 /* Convert to the desired target text format, if necessary */
594 if( lpTarget != lpSource && !lpTarget->hData16 && !lpTarget->hData32 )
596 INT src_chars, dst_chars, alloc_size;
597 LPCSTR lpstrS;
598 LPSTR lpstrT;
600 if (lpSource->hData32)
602 lpstrS = (LPSTR)GlobalLock(lpSource->hData32);
604 else
606 lpstrS = (LPSTR)GlobalLock16(lpSource->hData16);
609 if( !lpstrS ) return NULL;
611 /* Text always NULL terminated */
612 if(lpSource->wFormatID == CF_UNICODETEXT)
613 src_chars = strlenW((LPCWSTR)lpstrS)+1;
614 else
615 src_chars = strlen(lpstrS)+1;
617 /* Calculate number of characters in the destination buffer */
618 dst_chars = CLIPBOARD_ConvertText(lpSource->wFormatID, lpstrS, src_chars,
619 lpTarget->wFormatID, NULL, 0);
620 if(!dst_chars) return NULL;
622 TRACE("\tconverting from '%s' to '%s', %i chars\n",
623 lpSource->Name, lpTarget->Name, src_chars);
625 /* Convert characters to bytes */
626 if(lpTarget->wFormatID == CF_UNICODETEXT)
627 alloc_size = dst_chars * sizeof(WCHAR);
628 else
629 alloc_size = dst_chars;
631 lpTarget->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, alloc_size);
632 lpstrT = (LPSTR)GlobalLock(lpTarget->hData32);
634 if( lpstrT )
636 CLIPBOARD_ConvertText(lpSource->wFormatID, lpstrS, src_chars,
637 lpTarget->wFormatID, lpstrT, dst_chars);
638 GlobalUnlock(lpTarget->hData32);
640 else
641 lpTarget->hData32 = 0;
643 /* Unlock source */
644 if (lpSource->hData32)
645 GlobalUnlock(lpSource->hData32);
646 else
647 GlobalUnlock16(lpSource->hData16);
650 return (lpTarget->hData16 || lpTarget->hData32) ? lpTarget : NULL;
653 /**************************************************************************
654 * CLIPBOARD_EnumClipboardFormats (internal)
656 static UINT CLIPBOARD_EnumClipboardFormats( UINT wFormat )
658 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
659 BOOL bFormatPresent;
661 if (wFormat == 0) /* start from the beginning */
662 lpFormat = ClipFormats;
663 else
665 /* walk up to the specified format record */
667 if( !(lpFormat = __lookup_format( lpFormat, wFormat )) )
668 return 0;
669 lpFormat = lpFormat->NextFormat; /* right */
672 while(TRUE)
674 if (lpFormat == NULL) return 0;
676 if(CLIPBOARD_IsPresent(lpFormat->wFormatID))
677 break;
679 /* Query the driver if not yet in the cache */
680 if (!USER_Driver.pIsSelectionOwner())
682 if(lpFormat->wFormatID == CF_UNICODETEXT ||
683 lpFormat->wFormatID == CF_TEXT ||
684 lpFormat->wFormatID == CF_OEMTEXT)
686 if(USER_Driver.pIsClipboardFormatAvailable(CF_UNICODETEXT) ||
687 USER_Driver.pIsClipboardFormatAvailable(CF_TEXT) ||
688 USER_Driver.pIsClipboardFormatAvailable(CF_OEMTEXT))
689 bFormatPresent = TRUE;
690 else
691 bFormatPresent = FALSE;
693 else
694 bFormatPresent = USER_Driver.pIsClipboardFormatAvailable(lpFormat->wFormatID);
696 if(bFormatPresent)
697 break;
700 lpFormat = lpFormat->NextFormat;
703 TRACE("Next available format %d\n", lpFormat->wFormatID);
705 return lpFormat->wFormatID;
709 /**************************************************************************
710 * WIN32 Clipboard implementation
711 **************************************************************************/
713 /**************************************************************************
714 * OpenClipboard (USER32.@)
716 * Note: Netscape uses NULL hWnd to open the clipboard.
718 BOOL WINAPI OpenClipboard( HWND hWnd )
720 BOOL bRet;
722 TRACE("(%04x)...\n", hWnd);
724 if (!hClipLock)
726 hClipLock = GetCurrentTask();
728 /* Save current user of the clipboard */
729 hWndClipWindow = WIN_GetFullHandle( hWnd );
730 bCBHasChanged = FALSE;
731 bRet = TRUE;
733 else bRet = FALSE;
735 TRACE(" returning %i\n", bRet);
736 return bRet;
740 /**************************************************************************
741 * CloseClipboard (USER.138)
743 BOOL16 WINAPI CloseClipboard16(void)
745 return CloseClipboard();
749 /**************************************************************************
750 * CloseClipboard (USER32.@)
752 BOOL WINAPI CloseClipboard(void)
754 TRACE("()\n");
756 if (hClipLock == GetCurrentTask())
758 hWndClipWindow = 0;
760 if (bCBHasChanged && hWndViewer) SendMessageW( hWndViewer, WM_DRAWCLIPBOARD, 0, 0 );
761 hClipLock = 0;
763 return TRUE;
767 /**************************************************************************
768 * EmptyClipboard (USER.139)
770 BOOL16 WINAPI EmptyClipboard16(void)
772 return EmptyClipboard();
776 /**************************************************************************
777 * EmptyClipboard (USER32.@)
778 * Empties and acquires ownership of the clipboard
780 BOOL WINAPI EmptyClipboard(void)
782 TRACE("()\n");
784 if (hClipLock != GetCurrentTask())
786 WARN("Clipboard not opened by calling task!\n");
787 return FALSE;
790 /* destroy private objects */
792 if (hWndClipOwner) SendMessageW( hWndClipOwner, WM_DESTROYCLIPBOARD, 0, 0 );
794 /* empty the cache */
795 CLIPBOARD_EmptyCache(TRUE);
797 /* Assign ownership of the clipboard to the current client */
798 hWndClipOwner = hWndClipWindow;
800 /* Save the current task */
801 hTaskClipOwner = GetCurrentTask();
803 /* Tell the driver to acquire the selection */
804 USER_Driver.pAcquireClipboard();
806 return TRUE;
810 /**************************************************************************
811 * GetClipboardOwner (USER32.@)
812 * FIXME: Can't return the owner if the clipbard is owned by an external app
814 HWND WINAPI GetClipboardOwner(void)
816 TRACE("()\n");
817 return hWndClipOwner;
821 /**************************************************************************
822 * SetClipboardData (USER.141)
824 HANDLE16 WINAPI SetClipboardData16( UINT16 wFormat, HANDLE16 hData )
826 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
828 TRACE("(%04X, %04x) !\n", wFormat, hData);
830 /* NOTE: If the hData is zero and current owner doesn't match
831 * the window that opened the clipboard then this application
832 * is screwed because WM_RENDERFORMAT will go to the owner.
833 * (to become the owner it must call EmptyClipboard() before
834 * adding new data).
837 if( CLIPBOARD_IsLocked() || !lpFormat ||
838 (!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) )
840 WARN("Invalid hData or clipboard not opened by calling task!\n");
841 return 0;
844 /* Pass on the request to the driver */
845 USER_Driver.pSetClipboardData(wFormat);
847 if ( lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32 )
849 CLIPBOARD_DeleteRecord(lpFormat, TRUE);
851 /* delete existing CF_UNICODETEXT/CF_TEXT/CF_OEMTEXT aliases */
852 if(wFormat == CF_UNICODETEXT)
854 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
855 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
857 else if(wFormat == CF_TEXT)
859 CLIPBOARD_DeleteRecord(&ClipFormats[CF_UNICODETEXT-1], TRUE);
860 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
862 else if(wFormat == CF_OEMTEXT)
864 CLIPBOARD_DeleteRecord(&ClipFormats[CF_UNICODETEXT-1], TRUE);
865 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
869 bCBHasChanged = TRUE;
870 lpFormat->wDataPresent = 1;
871 lpFormat->hData16 = hData; /* 0 is legal, see WM_RENDERFORMAT */
872 lpFormat->hData32 = 0;
874 return lpFormat->hData16;
878 /**************************************************************************
879 * SetClipboardData (USER32.@)
881 HANDLE WINAPI SetClipboardData( UINT wFormat, HANDLE hData )
883 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
885 TRACE("(%08X, %08x) !\n", wFormat, hData);
887 /* NOTE: If the hData is zero and current owner doesn't match
888 * the window that opened the clipboard then this application
889 * is screwed because WM_RENDERFORMAT will go to the owner.
890 * (to become the owner it must call EmptyClipboard() before
891 * adding new data).
894 if( CLIPBOARD_IsLocked() || !lpFormat ||
895 (!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) )
897 WARN("Invalid hData or clipboard not opened by calling task!\n");
898 return 0;
901 /* Tell the driver to acquire the selection */
902 USER_Driver.pAcquireClipboard();
904 if ( lpFormat->wDataPresent &&
905 (lpFormat->hData16 || lpFormat->hData32) )
907 CLIPBOARD_DeleteRecord(lpFormat, TRUE);
909 /* delete existing CF_UNICODETEXT/CF_TEXT/CF_OEMTEXT aliases */
910 if(wFormat == CF_UNICODETEXT)
912 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
913 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
915 else if(wFormat == CF_TEXT)
917 CLIPBOARD_DeleteRecord(&ClipFormats[CF_UNICODETEXT-1], TRUE);
918 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
920 else if(wFormat == CF_OEMTEXT)
922 CLIPBOARD_DeleteRecord(&ClipFormats[CF_UNICODETEXT-1], TRUE);
923 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
927 bCBHasChanged = TRUE;
928 lpFormat->wDataPresent = 1;
929 lpFormat->hDataSrc32 = hData; /* Save the source handle */
932 * Make a shared duplicate if the memory is not shared
933 * TODO: What should be done for non-memory objects
935 if ( CLIPBOARD_IsMemoryObject(wFormat) && hData && !(GlobalFlags(hData) & GMEM_DDESHARE) )
936 lpFormat->hData32 = CLIPBOARD_GlobalDupMem( hData );
937 else
938 lpFormat->hData32 = hData; /* 0 is legal, see WM_RENDERFORMAT */
940 lpFormat->hData16 = 0;
942 return lpFormat->hData32; /* Should we return lpFormat->hDataSrc32 */
946 /**************************************************************************
947 * GetClipboardData (USER.142)
949 HANDLE16 WINAPI GetClipboardData16( UINT16 wFormat )
951 LPWINE_CLIPFORMAT lpRender = ClipFormats;
953 TRACE("(%04X)\n", wFormat);
955 if (CLIPBOARD_IsLocked())
957 WARN("Clipboard not opened by calling task!\n");
958 return 0;
961 if( wFormat == CF_UNICODETEXT || wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
963 lpRender = CLIPBOARD_RenderText(wFormat);
964 if ( !lpRender ) return 0;
966 else
968 lpRender = __lookup_format( ClipFormats, wFormat );
969 if( !lpRender || !CLIPBOARD_RenderFormat(lpRender) ) return 0;
972 /* Convert between 32 -> 16 bit data, if necessary */
973 if( lpRender->hData32 && !lpRender->hData16
974 && CLIPBOARD_IsMemoryObject(wFormat) )
976 int size;
977 if( lpRender->wFormatID == CF_METAFILEPICT )
978 size = sizeof( METAFILEPICT16 );
979 else
980 size = GlobalSize(lpRender->hData32);
982 lpRender->hData16 = GlobalAlloc16(GMEM_ZEROINIT, size);
983 if( !lpRender->hData16 )
984 ERR("(%04X) -- not enough memory in 16b heap\n", wFormat);
985 else
987 if( lpRender->wFormatID == CF_METAFILEPICT )
989 FIXME("\timplement function CopyMetaFilePict32to16\n");
990 FIXME("\tin the appropriate file.\n");
991 #ifdef SOMEONE_IMPLEMENTED_ME
992 CopyMetaFilePict32to16( GlobalLock16(lpRender->hData16),
993 GlobalLock(lpRender->hData32) );
994 #endif
996 else
998 memcpy( GlobalLock16(lpRender->hData16),
999 GlobalLock(lpRender->hData32),
1000 size );
1002 GlobalUnlock16(lpRender->hData16);
1003 GlobalUnlock(lpRender->hData32);
1007 TRACE("\treturning %04x (type %i)\n",
1008 lpRender->hData16, lpRender->wFormatID);
1009 return lpRender->hData16;
1013 /**************************************************************************
1014 * GetClipboardData (USER32.@)
1016 HANDLE WINAPI GetClipboardData( UINT wFormat )
1018 LPWINE_CLIPFORMAT lpRender = ClipFormats;
1020 TRACE("(%08X)\n", wFormat);
1022 if (CLIPBOARD_IsLocked())
1024 WARN("Clipboard not opened by calling task!\n");
1025 return 0;
1028 if( wFormat == CF_UNICODETEXT || wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
1030 lpRender = CLIPBOARD_RenderText(wFormat);
1031 if ( !lpRender ) return 0;
1033 else
1035 lpRender = __lookup_format( ClipFormats, wFormat );
1036 if( !lpRender || !CLIPBOARD_RenderFormat(lpRender) ) return 0;
1039 /* Convert between 16 -> 32 bit data, if necessary */
1040 if( lpRender->hData16 && !lpRender->hData32
1041 && CLIPBOARD_IsMemoryObject(wFormat) )
1043 int size;
1044 if( lpRender->wFormatID == CF_METAFILEPICT )
1045 size = sizeof( METAFILEPICT );
1046 else
1047 size = GlobalSize16(lpRender->hData16);
1048 lpRender->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE,
1049 size);
1050 if( lpRender->wFormatID == CF_METAFILEPICT )
1052 FIXME("\timplement function CopyMetaFilePict16to32\n");
1053 FIXME("\tin the appropriate file.\n");
1054 #ifdef SOMEONE_IMPLEMENTED_ME
1055 CopyMetaFilePict16to32( GlobalLock16(lpRender->hData32),
1056 GlobalLock(lpRender->hData16) );
1057 #endif
1059 else
1061 memcpy( GlobalLock(lpRender->hData32),
1062 GlobalLock16(lpRender->hData16),
1063 size );
1065 GlobalUnlock(lpRender->hData32);
1066 GlobalUnlock16(lpRender->hData16);
1069 TRACE("\treturning %04x (type %i)\n",
1070 lpRender->hData32, lpRender->wFormatID);
1071 return lpRender->hData32;
1075 /**************************************************************************
1076 * CountClipboardFormats (USER.143)
1078 INT16 WINAPI CountClipboardFormats16(void)
1080 return CountClipboardFormats();
1084 /**************************************************************************
1085 * CountClipboardFormats (USER32.@)
1087 INT WINAPI CountClipboardFormats(void)
1089 INT FormatCount = 0;
1090 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
1092 TRACE("()\n");
1094 while(TRUE)
1096 if (lpFormat == NULL) break;
1098 if( lpFormat->wFormatID != CF_TEXT ) /* Don't count CF_TEXT */
1101 * The format is available if either:
1102 * 1. The data is already in the cache.
1103 * 2. The selection is not owned by us(WINE) and the data is
1104 * available to the clipboard driver.
1106 if ( lpFormat->wDataPresent ||
1107 ( !USER_Driver.pIsSelectionOwner()
1108 && USER_Driver.pIsClipboardFormatAvailable( lpFormat->wFormatID ) ) )
1110 TRACE("\tdata found for format 0x%04x(%s)\n",
1111 lpFormat->wFormatID, CLIPBOARD_GetFormatName(lpFormat->wFormatID));
1112 FormatCount++;
1116 lpFormat = lpFormat->NextFormat;
1119 /* these are equivalent, adjust the total */
1120 FormatCount += (ClipFormats[CF_UNICODETEXT-1].wDataPresent ||
1121 ClipFormats[CF_TEXT-1].wDataPresent ||
1122 ClipFormats[CF_OEMTEXT-1].wDataPresent) ? 1 : 0;
1124 TRACE("\ttotal %d\n", FormatCount);
1125 return FormatCount;
1128 /**************************************************************************
1129 * EnumClipboardFormats (USER.144)
1131 UINT16 WINAPI EnumClipboardFormats16( UINT16 wFormat )
1133 return EnumClipboardFormats( wFormat );
1137 /**************************************************************************
1138 * EnumClipboardFormats (USER32.@)
1140 UINT WINAPI EnumClipboardFormats( UINT wFormat )
1142 TRACE("(%04X)\n", wFormat);
1144 if (CLIPBOARD_IsLocked())
1146 WARN("Clipboard not opened by calling task!\n");
1147 return 0;
1150 return CLIPBOARD_EnumClipboardFormats(wFormat);
1154 /**************************************************************************
1155 * RegisterClipboardFormatA (USER32.@)
1157 UINT WINAPI RegisterClipboardFormatA( LPCSTR FormatName )
1159 LPWINE_CLIPFORMAT lpNewFormat;
1160 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
1162 if (FormatName == NULL) return 0;
1164 TRACE("('%s') !\n", FormatName);
1166 /* walk format chain to see if it's already registered */
1168 while(TRUE)
1170 if ( !strcmp(lpFormat->Name,FormatName) )
1172 lpFormat->wRefCount++;
1173 return lpFormat->wFormatID;
1176 if ( lpFormat->NextFormat == NULL ) break;
1178 lpFormat = lpFormat->NextFormat;
1181 /* allocate storage for new format entry */
1183 lpNewFormat = (LPWINE_CLIPFORMAT)HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_CLIPFORMAT));
1184 if(lpNewFormat == NULL) {
1185 WARN("No more memory for a new format!\n");
1186 return 0;
1188 lpFormat->NextFormat = lpNewFormat;
1189 lpNewFormat->wFormatID = LastRegFormat;
1190 lpNewFormat->wRefCount = 1;
1192 if (!(lpNewFormat->Name = HeapAlloc(GetProcessHeap(), 0, strlen(FormatName)+1 )))
1194 WARN("No more memory for the new format name!\n");
1195 HeapFree(GetProcessHeap(), 0, lpNewFormat);
1196 return 0;
1198 strcpy( lpNewFormat->Name, FormatName );
1200 lpNewFormat->wDataPresent = 0;
1201 lpNewFormat->hData16 = 0;
1202 lpNewFormat->hDataSrc32 = 0;
1203 lpNewFormat->hData32 = 0;
1204 lpNewFormat->drvData = 0;
1205 lpNewFormat->PrevFormat = lpFormat;
1206 lpNewFormat->NextFormat = NULL;
1208 /* Pass on the registration request to the driver */
1209 USER_Driver.pRegisterClipboardFormat( FormatName );
1211 return LastRegFormat++;
1215 /**************************************************************************
1216 * RegisterClipboardFormat (USER.145)
1218 UINT16 WINAPI RegisterClipboardFormat16( LPCSTR FormatName )
1220 return RegisterClipboardFormatA( FormatName );
1224 /**************************************************************************
1225 * RegisterClipboardFormatW (USER32.@)
1227 UINT WINAPI RegisterClipboardFormatW( LPCWSTR formatName )
1229 LPSTR aFormat = HEAP_strdupWtoA( GetProcessHeap(), 0, formatName );
1230 UINT ret = RegisterClipboardFormatA( aFormat );
1231 HeapFree( GetProcessHeap(), 0, aFormat );
1232 return ret;
1236 /**************************************************************************
1237 * GetClipboardFormatName (USER.146)
1239 INT16 WINAPI GetClipboardFormatName16( UINT16 wFormat, LPSTR retStr, INT16 maxlen )
1241 return GetClipboardFormatNameA( wFormat, retStr, maxlen );
1245 /**************************************************************************
1246 * GetClipboardFormatNameA (USER32.@)
1248 INT WINAPI GetClipboardFormatNameA( UINT wFormat, LPSTR retStr, INT maxlen )
1250 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
1252 TRACE("(%04X, %p, %d) !\n", wFormat, retStr, maxlen);
1254 if (lpFormat == NULL || lpFormat->Name == NULL ||
1255 lpFormat->wFormatID < CF_REGFORMATBASE) return 0;
1257 TRACE("Name='%s' !\n", lpFormat->Name);
1259 lstrcpynA( retStr, lpFormat->Name, maxlen );
1260 return strlen(retStr);
1264 /**************************************************************************
1265 * GetClipboardFormatNameW (USER32.@)
1267 INT WINAPI GetClipboardFormatNameW( UINT wFormat, LPWSTR retStr, INT maxlen )
1269 INT ret;
1270 LPSTR p = HeapAlloc( GetProcessHeap(), 0, maxlen );
1271 if(p == NULL) return 0; /* FIXME: is this the correct failure value? */
1273 ret = GetClipboardFormatNameA( wFormat, p, maxlen );
1275 if (maxlen > 0 && !MultiByteToWideChar( CP_ACP, 0, p, -1, retStr, maxlen ))
1276 retStr[maxlen-1] = 0;
1277 HeapFree( GetProcessHeap(), 0, p );
1278 return ret;
1282 /**************************************************************************
1283 * SetClipboardViewer (USER32.@)
1285 HWND WINAPI SetClipboardViewer( HWND hWnd )
1287 HWND hwndPrev = hWndViewer;
1289 TRACE("(%04x): returning %04x\n", hWnd, hwndPrev);
1291 hWndViewer = WIN_GetFullHandle( hWnd );
1292 return hwndPrev;
1296 /**************************************************************************
1297 * GetClipboardViewer (USER32.@)
1299 HWND WINAPI GetClipboardViewer(void)
1301 TRACE("()\n");
1302 return hWndViewer;
1306 /**************************************************************************
1307 * ChangeClipboardChain (USER32.@)
1309 BOOL WINAPI ChangeClipboardChain(HWND hWnd, HWND hWndNext)
1311 BOOL bRet = 0;
1313 FIXME("(0x%04x, 0x%04x): stub?\n", hWnd, hWndNext);
1315 if( hWndViewer )
1316 bRet = !SendMessageW( hWndViewer, WM_CHANGECBCHAIN, (WPARAM)hWnd, (LPARAM)hWndNext );
1317 else
1318 WARN("hWndViewer is lost\n");
1320 if( WIN_GetFullHandle(hWnd) == hWndViewer ) hWndViewer = WIN_GetFullHandle( hWndNext );
1322 return bRet;
1326 /**************************************************************************
1327 * IsClipboardFormatAvailable (USER.193)
1329 BOOL16 WINAPI IsClipboardFormatAvailable16( UINT16 wFormat )
1331 return IsClipboardFormatAvailable( wFormat );
1335 /**************************************************************************
1336 * IsClipboardFormatAvailable (USER32.@)
1338 BOOL WINAPI IsClipboardFormatAvailable( UINT wFormat )
1340 BOOL bRet;
1342 if (wFormat == 0) /* Reject this case quickly */
1343 bRet = FALSE;
1344 else
1346 UINT iret = CLIPBOARD_EnumClipboardFormats(wFormat - 1);
1347 if ((wFormat == CF_TEXT) || (wFormat == CF_OEMTEXT) || (wFormat == CF_UNICODETEXT))
1348 bRet = ((iret == CF_TEXT) || (iret == CF_OEMTEXT) || (iret == CF_UNICODETEXT));
1349 else
1350 bRet = iret == wFormat;
1352 TRACE("(%04X)- ret(%d)\n", wFormat, bRet);
1353 return bRet;
1357 /**************************************************************************
1358 * GetOpenClipboardWindow (USER32.@)
1359 * FIXME: This wont work if an external app owns the selection
1361 HWND WINAPI GetOpenClipboardWindow(void)
1363 TRACE("()\n");
1364 return hWndClipWindow;
1368 /**************************************************************************
1369 * GetPriorityClipboardFormat (USER32.@)
1371 INT WINAPI GetPriorityClipboardFormat( UINT *list, INT nCount )
1373 int i;
1374 TRACE("()\n");
1376 if(CountClipboardFormats() == 0) return 0;
1378 for (i = 0; i < nCount; i++)
1379 if (IsClipboardFormatAvailable( list[i] )) return list[i];
1380 return -1;
1384 /**************************************************************************
1385 * GetClipboardSequenceNumber (USER32.@)
1386 * Supported on Win2k/Win98
1387 * MSDN: Windows clipboard code keeps a serial number for the clipboard
1388 * for each window station. The number is incremented whenever the
1389 * contents change or are emptied.
1390 * If you do not have WINSTA_ACCESSCLIPBOARD then the function returns 0
1392 DWORD WINAPI GetClipboardSequenceNumber(VOID)
1394 FIXME("Returning 0, see windows/clipboard.c\n");
1395 /* FIXME: Use serial numbers */
1396 return 0;