Avoid dependencies on y.tab.h.
[wine/multimedia.git] / windows / clipboard.c
blob9927eda6a56abbe364db009a186062bb90bf2f08
1 /*
2 * WIN32 clipboard implementation
4 * Copyright 1994 Martin Ayotte
5 * 1996 Alex Korobka
6 * 1999 Noel Borthwick
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * NOTES:
23 * This file contains the implementation for the WIN32 Clipboard API
24 * and Wine's internal clipboard cache.
25 * The actual contents of the clipboard are held in the clipboard cache.
26 * The internal implementation talks to a "clipboard driver" to fill or
27 * expose the cache to the native device. (Currently only the X11 and
28 * TTY clipboard driver are available)
31 #include <stdlib.h>
32 #include <sys/types.h>
33 #include <fcntl.h>
34 #include <unistd.h>
35 #include <string.h>
37 #include "windef.h"
38 #include "winbase.h"
39 #include "wingdi.h"
40 #include "winuser.h"
41 #include "wine/winuser16.h"
42 #include "wine/winbase16.h"
43 #include "heap.h"
44 #include "user.h"
45 #include "win.h"
46 #include "clipboard.h"
47 #include "wine/debug.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(clipboard);
51 #define CF_REGFORMATBASE 0xC000
53 /**************************************************************************
54 * Clipboard context global variables
57 static HANDLE hClipLock = 0;
58 static BOOL bCBHasChanged = FALSE;
60 static HWND hWndClipWindow; /* window that last opened clipboard */
61 static HWND hWndClipOwner; /* current clipboard owner */
62 static HANDLE16 hTaskClipOwner; /* clipboard owner's task */
63 static HWND hWndViewer; /* start of viewers chain */
65 static WORD LastRegFormat = CF_REGFORMATBASE;
67 /* Clipboard cache initial data.
68 * WARNING: This data ordering is dependent on the WINE_CLIPFORMAT structure
69 * declared in clipboard.h
71 WINE_CLIPFORMAT ClipFormats[] = {
72 { CF_TEXT, 1, 0, "Text", 0, 0, 0, 0, NULL, &ClipFormats[1]},
73 { CF_BITMAP, 1, 0, "Bitmap", 0, 0, 0, 0, &ClipFormats[0], &ClipFormats[2]},
74 { CF_METAFILEPICT, 1, 0, "MetaFile Picture", 0, 0, 0, 0, &ClipFormats[1], &ClipFormats[3]},
75 { CF_SYLK, 1, 0, "Sylk", 0, 0, 0, 0, &ClipFormats[2], &ClipFormats[4]},
76 { CF_DIF, 1, 0, "DIF", 0, 0, 0, 0, &ClipFormats[3], &ClipFormats[5]},
77 { CF_TIFF, 1, 0, "TIFF", 0, 0, 0, 0, &ClipFormats[4], &ClipFormats[6]},
78 { CF_OEMTEXT, 1, 0, "OEM Text", 0, 0, 0, 0, &ClipFormats[5], &ClipFormats[7]},
79 { CF_DIB, 1, 0, "DIB", 0, 0, 0, 0, &ClipFormats[6], &ClipFormats[8]},
80 { CF_PALETTE, 1, 0, "Palette", 0, 0, 0, 0, &ClipFormats[7], &ClipFormats[9]},
81 { CF_PENDATA, 1, 0, "PenData", 0, 0, 0, 0, &ClipFormats[8], &ClipFormats[10]},
82 { CF_RIFF, 1, 0, "RIFF", 0, 0, 0, 0, &ClipFormats[9], &ClipFormats[11]},
83 { CF_WAVE, 1, 0, "Wave", 0, 0, 0, 0, &ClipFormats[10], &ClipFormats[12]},
84 { CF_UNICODETEXT, 1, 0, "Unicode Text", 0, 0, 0, 0, &ClipFormats[11], &ClipFormats[13]},
85 { CF_OWNERDISPLAY, 1, 0, "Owner Display", 0, 0, 0, 0, &ClipFormats[12], &ClipFormats[14]},
86 { CF_DSPTEXT, 1, 0, "DSPText", 0, 0, 0, 0, &ClipFormats[13], &ClipFormats[15]},
87 { CF_DSPMETAFILEPICT, 1, 0, "DSPMetaFile Picture", 0, 0, 0, 0, &ClipFormats[14], &ClipFormats[16]},
88 { CF_DSPBITMAP, 1, 0, "DSPBitmap", 0, 0, 0, 0, &ClipFormats[15], &ClipFormats[17]},
89 { CF_HDROP, 1, 0, "HDROP", 0, 0, 0, 0, &ClipFormats[16], NULL}
93 /**************************************************************************
94 * Internal Clipboard implementation methods
95 **************************************************************************/
98 /**************************************************************************
99 * CLIPBOARD_LookupFormat
101 static LPWINE_CLIPFORMAT __lookup_format( LPWINE_CLIPFORMAT lpFormat, WORD wID )
103 while(TRUE)
105 if (lpFormat == NULL ||
106 lpFormat->wFormatID == wID) break;
107 lpFormat = lpFormat->NextFormat;
109 return lpFormat;
112 LPWINE_CLIPFORMAT CLIPBOARD_LookupFormat( WORD wID )
114 return __lookup_format( ClipFormats, wID );
117 /**************************************************************************
118 * CLIPBOARD_IsLocked
119 * Check if the clipboard cache is available to the caller
121 BOOL CLIPBOARD_IsLocked()
123 BOOL bIsLocked = TRUE;
124 HANDLE16 hTaskCur = GetCurrentTask();
127 * The clipboard is available:
128 * 1. if the caller's task has opened the clipboard,
129 * or
130 * 2. if the caller is the clipboard owners task, AND is responding to a
131 * WM_RENDERFORMAT message.
133 if ( hClipLock == hTaskCur )
134 bIsLocked = FALSE;
136 else if ( hTaskCur == hTaskClipOwner )
138 /* Check if we're currently executing inside a window procedure
139 * called in response to a WM_RENDERFORMAT message. A WM_RENDERFORMAT
140 * handler is not permitted to open the clipboard since it has been opened
141 * by another client. However the handler must have access to the
142 * clipboard in order to update data in response to this message.
144 #if 0
145 MESSAGEQUEUE *queue = QUEUE_Current();
147 if ( queue
148 && queue->smWaiting
149 && queue->smWaiting->msg == WM_RENDERFORMAT
150 && queue->smWaiting->hSrcQueue
152 bIsLocked = FALSE;
153 #else
154 /* FIXME: queue check no longer possible */
155 bIsLocked = FALSE;
156 #endif
159 return bIsLocked;
162 /**************************************************************************
163 * CLIPBOARD_ReleaseOwner
164 * Gives up ownership of the clipboard
166 void CLIPBOARD_ReleaseOwner()
168 hWndClipOwner = 0;
169 hTaskClipOwner = 0;
172 /**************************************************************************
173 * CLIPBOARD_GlobalFreeProc
175 * This is a callback mechanism to allow HGLOBAL data to be released in
176 * the context of the process which allocated it. We post a WM_TIMER message
177 * to the owner window(in CLIPBOARD_DeleteRecord) and destroy the data(in idEvent)
178 * in this WndProc, which is invoked when the apps message loop calls DispatchMessage.
179 * This technique is discussed in Matt Pietrek's "Under the Hood".
180 * An article describing the same may be found in MSDN by searching for WM_TIMER.
181 * Note that this mechanism will probably stop working when WINE supports
182 * address space separation. When "queue events" are implemented in Wine we
183 * should switch to using that mechanism, since it is more robust and does not
184 * require a procedure address to be passed. See the SetWinEventHook API for
185 * more info on this.
187 VOID CALLBACK CLIPBOARD_GlobalFreeProc( HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime )
189 /* idEvent is the HGLOBAL to be deleted */
190 GlobalFree( (HGLOBAL)idEvent );
193 /**************************************************************************
194 * CLIPBOARD_DeleteRecord
196 void CLIPBOARD_DeleteRecord(LPWINE_CLIPFORMAT lpFormat, BOOL bChange)
198 if( (lpFormat->wFormatID >= CF_GDIOBJFIRST &&
199 lpFormat->wFormatID <= CF_GDIOBJLAST) || lpFormat->wFormatID == CF_BITMAP
200 || lpFormat->wFormatID == CF_PALETTE)
202 if (lpFormat->hData32)
203 DeleteObject(lpFormat->hData32);
204 if (lpFormat->hData16)
205 DeleteObject(lpFormat->hData16);
207 else if( lpFormat->wFormatID == CF_METAFILEPICT )
209 if (lpFormat->hData32)
211 DeleteMetaFile( ((METAFILEPICT *)GlobalLock( lpFormat->hData32 ))->hMF );
212 PostMessageA(hWndClipOwner, WM_TIMER,
213 (WPARAM)lpFormat->hData32, (LPARAM)CLIPBOARD_GlobalFreeProc);
214 if (lpFormat->hDataSrc32)
216 /* Release lpFormat->hData32 in the context of the process which created it.
217 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
218 * GlobalFree(lpFormat->hDataSrc32);
220 PostMessageA(hWndClipOwner, WM_TIMER,
221 (WPARAM)lpFormat->hDataSrc32, (LPARAM)CLIPBOARD_GlobalFreeProc);
224 if (lpFormat->hData16)
225 /* HMETAFILE16 and HMETAFILE32 are apparently the same thing,
226 and a shallow copy is enough to share a METAFILEPICT
227 structure between 16bit and 32bit clipboards. The MetaFile
228 should of course only be deleted once. */
229 GlobalFree16(lpFormat->hData16);
231 if (lpFormat->hData16)
233 DeleteMetaFile16( ((METAFILEPICT16 *)GlobalLock16( lpFormat->hData16 ))->hMF );
234 GlobalFree16(lpFormat->hData16);
237 else
239 if (lpFormat->hData32)
241 /* Release lpFormat->hData32 in the context of the process which created it.
242 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
243 * GlobalFree( lpFormat->hData32 );
245 PostMessageA(hWndClipOwner, WM_TIMER,
246 (WPARAM)lpFormat->hData32, (LPARAM)CLIPBOARD_GlobalFreeProc);
248 if (lpFormat->hDataSrc32)
250 /* Release lpFormat->hData32 in the context of the process which created it.
251 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
252 * GlobalFree(lpFormat->hDataSrc32);
254 PostMessageA(hWndClipOwner, WM_TIMER,
255 (WPARAM)lpFormat->hDataSrc32, (LPARAM)CLIPBOARD_GlobalFreeProc);
257 if (lpFormat->hData16)
258 GlobalFree16(lpFormat->hData16);
261 lpFormat->wDataPresent = 0;
262 lpFormat->hData16 = 0;
263 lpFormat->hData32 = 0;
264 lpFormat->hDataSrc32 = 0;
265 lpFormat->drvData = 0;
267 if( bChange ) bCBHasChanged = TRUE;
270 /**************************************************************************
271 * CLIPBOARD_EmptyCache
273 void CLIPBOARD_EmptyCache( BOOL bChange )
275 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
277 while(lpFormat)
279 if ( lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32 )
280 CLIPBOARD_DeleteRecord( lpFormat, bChange );
282 lpFormat = lpFormat->NextFormat;
286 /**************************************************************************
287 * CLIPBOARD_IsPresent
289 BOOL CLIPBOARD_IsPresent(WORD wFormat)
291 /* special case */
293 if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT || wFormat == CF_UNICODETEXT )
294 return ClipFormats[CF_TEXT-1].wDataPresent ||
295 ClipFormats[CF_OEMTEXT-1].wDataPresent ||
296 ClipFormats[CF_UNICODETEXT-1].wDataPresent;
297 else
299 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
300 if( lpFormat ) return (lpFormat->wDataPresent);
302 return FALSE;
305 /**************************************************************************
306 * CLIPBOARD_IsCacheRendered
307 * Checks if any data needs to be rendered to the clipboard cache
308 * RETURNS:
309 * TRUE - All clipboard data is available in the cache
310 * FALSE - Some data is marked for delayed render and needs rendering
312 BOOL CLIPBOARD_IsCacheRendered()
314 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
316 /* check if all formats were rendered */
317 while(lpFormat)
319 if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
320 return FALSE;
322 lpFormat = lpFormat->NextFormat;
325 return TRUE;
329 /**************************************************************************
330 * CLIPBOARD_IsMemoryObject
331 * Tests if the clipboard format specifies a memory object
333 BOOL CLIPBOARD_IsMemoryObject( WORD wFormat )
335 switch(wFormat)
337 case CF_BITMAP:
338 case CF_METAFILEPICT:
339 case CF_DSPTEXT:
340 case CF_ENHMETAFILE:
341 case CF_HDROP:
342 case CF_PALETTE:
343 case CF_PENDATA:
344 return FALSE;
345 default:
346 return TRUE;
350 /***********************************************************************
351 * CLIPBOARD_GlobalDupMem( HGLOBAL )
352 * Helper method to duplicate an HGLOBAL chunk of memory into shared memory
354 HGLOBAL CLIPBOARD_GlobalDupMem( HGLOBAL hGlobalSrc )
356 HGLOBAL hGlobalDest;
357 PVOID pGlobalSrc, pGlobalDest;
358 DWORD cBytes;
360 if ( !hGlobalSrc )
361 return 0;
363 cBytes = GlobalSize(hGlobalSrc);
364 if ( 0 == cBytes )
365 return 0;
367 /* Turn on the DDESHARE and _MOVEABLE flags explicitly */
368 hGlobalDest = GlobalAlloc( GlobalFlags(hGlobalSrc) | GMEM_DDESHARE | GMEM_MOVEABLE,
369 cBytes );
370 if ( !hGlobalDest )
371 return 0;
373 pGlobalSrc = GlobalLock(hGlobalSrc);
374 pGlobalDest = GlobalLock(hGlobalDest);
375 if ( !pGlobalSrc || !pGlobalDest )
376 return 0;
378 memcpy(pGlobalDest, pGlobalSrc, cBytes);
380 GlobalUnlock(hGlobalSrc);
381 GlobalUnlock(hGlobalDest);
383 return hGlobalDest;
386 /**************************************************************************
387 * CLIPBOARD_GetFormatName
388 * Gets the format name associated with an ID
390 char * CLIPBOARD_GetFormatName(UINT wFormat)
392 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
393 return (lpFormat) ? lpFormat->Name : NULL;
397 /**************************************************************************
398 * CLIPBOARD_RenderFormat
400 static BOOL CLIPBOARD_RenderFormat(LPWINE_CLIPFORMAT lpFormat)
403 * If WINE is not the selection owner, and the format is available
404 * we must ask the driver to render the data to the clipboard cache.
406 TRACE("enter format=%d\n", lpFormat->wFormatID);
407 if ( !USER_Driver.pIsSelectionOwner()
408 && USER_Driver.pIsClipboardFormatAvailable( lpFormat->wFormatID ) )
410 if ( !USER_Driver.pGetClipboardData( lpFormat->wFormatID ) )
411 return FALSE;
414 * If Wine owns the clipboard, and the data is marked for delayed render,
415 * render it now.
417 else if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
419 if( IsWindow(hWndClipOwner) )
421 /* Send a WM_RENDERFORMAT message to notify the owner to render the
422 * data requested into the clipboard.
424 TRACE("Sending WM_RENDERFORMAT message\n");
425 SendMessageW( hWndClipOwner, WM_RENDERFORMAT, (WPARAM)lpFormat->wFormatID, 0 );
427 else
429 WARN("\thWndClipOwner (%04x) is lost!\n",
430 hWndClipOwner);
431 CLIPBOARD_ReleaseOwner();
432 lpFormat->wDataPresent = 0;
433 return FALSE;
437 return (lpFormat->hData16 || lpFormat->hData32) ? TRUE : FALSE;
440 /**************************************************************************
441 * CLIPBOARD_ConvertText
442 * Returns number of required/converted characters - not bytes!
444 static INT CLIPBOARD_ConvertText(WORD src_fmt, void const *src, INT src_size,
445 WORD dst_fmt, void *dst, INT dst_size)
447 UINT cp;
449 if(src_fmt == CF_UNICODETEXT)
451 switch(dst_fmt)
453 case CF_TEXT:
454 cp = CP_ACP;
455 break;
456 case CF_OEMTEXT:
457 cp = CP_OEMCP;
458 break;
459 default:
460 return 0;
462 return WideCharToMultiByte(cp, 0, src, src_size, dst, dst_size, NULL, NULL);
465 if(dst_fmt == CF_UNICODETEXT)
467 switch(src_fmt)
469 case CF_TEXT:
470 cp = CP_ACP;
471 break;
472 case CF_OEMTEXT:
473 cp = CP_OEMCP;
474 break;
475 default:
476 return 0;
478 return MultiByteToWideChar(cp, 0, src, src_size, dst, dst_size);
481 if(!dst_size) return src_size;
483 if(dst_size > src_size) dst_size = src_size;
485 if(src_fmt == CF_TEXT )
486 CharToOemBuffA(src, dst, dst_size);
487 else
488 OemToCharBuffA(src, dst, dst_size);
490 return dst_size;
493 /**************************************************************************
494 * CLIPBOARD_RenderText
496 * Renders text to the clipboard buffer converting between UNIX and DOS formats.
498 * RETURNS: pointer to the WINE_CLIPFORMAT if successful, NULL otherwise
500 * FIXME: Should be a pair of driver functions that convert between OEM text and Windows.
503 static LPWINE_CLIPFORMAT CLIPBOARD_RenderText( UINT wFormat )
505 LPWINE_CLIPFORMAT lpSource = ClipFormats;
506 LPWINE_CLIPFORMAT lpTarget = NULL;
507 BOOL foundData = FALSE;
509 /* Asked for CF_TEXT */
510 if( wFormat == CF_TEXT)
512 if(ClipFormats[CF_TEXT-1].wDataPresent)
514 lpSource = &ClipFormats[CF_TEXT-1];
515 lpTarget = &ClipFormats[CF_TEXT-1];
516 foundData = TRUE;
517 TRACE("\t TEXT -> TEXT\n");
519 else if(ClipFormats[CF_UNICODETEXT-1].wDataPresent)
521 /* Convert UNICODETEXT -> TEXT */
522 lpSource = &ClipFormats[CF_UNICODETEXT-1];
523 lpTarget = &ClipFormats[CF_TEXT-1];
524 foundData = TRUE;
525 TRACE("\tUNICODETEXT -> TEXT\n");
527 else if(ClipFormats[CF_OEMTEXT-1].wDataPresent)
529 /* Convert OEMTEXT -> TEXT */
530 lpSource = &ClipFormats[CF_OEMTEXT-1];
531 lpTarget = &ClipFormats[CF_TEXT-1];
532 foundData = TRUE;
533 TRACE("\tOEMTEXT -> TEXT\n");
536 /* Asked for CF_OEMTEXT */
537 else if( wFormat == CF_OEMTEXT)
539 if(ClipFormats[CF_OEMTEXT-1].wDataPresent)
541 lpSource = &ClipFormats[CF_OEMTEXT-1];
542 lpTarget = &ClipFormats[CF_OEMTEXT-1];
543 foundData = TRUE;
544 TRACE("\tOEMTEXT -> OEMTEXT\n");
546 else if(ClipFormats[CF_UNICODETEXT-1].wDataPresent)
548 /* Convert UNICODETEXT -> OEMTEXT */
549 lpSource = &ClipFormats[CF_UNICODETEXT-1];
550 lpTarget = &ClipFormats[CF_OEMTEXT-1];
551 foundData = TRUE;
552 TRACE("\tUNICODETEXT -> OEMTEXT\n");
554 else if(ClipFormats[CF_TEXT-1].wDataPresent)
556 /* Convert TEXT -> OEMTEXT */
557 lpSource = &ClipFormats[CF_TEXT-1];
558 lpTarget = &ClipFormats[CF_OEMTEXT-1];
559 foundData = TRUE;
560 TRACE("\tTEXT -> OEMTEXT\n");
563 /* Asked for CF_UNICODETEXT */
564 else if( wFormat == CF_UNICODETEXT )
566 if(ClipFormats[CF_UNICODETEXT-1].wDataPresent)
568 lpSource = &ClipFormats[CF_UNICODETEXT-1];
569 lpTarget = &ClipFormats[CF_UNICODETEXT-1];
570 foundData = TRUE;
571 TRACE("\tUNICODETEXT -> UNICODETEXT\n");
573 else if(ClipFormats[CF_TEXT-1].wDataPresent)
575 /* Convert TEXT -> UNICODETEXT */
576 lpSource = &ClipFormats[CF_TEXT-1];
577 lpTarget = &ClipFormats[CF_UNICODETEXT-1];
578 foundData = TRUE;
579 TRACE("\tTEXT -> UNICODETEXT\n");
581 else if(ClipFormats[CF_OEMTEXT-1].wDataPresent)
583 /* Convert OEMTEXT -> UNICODETEXT */
584 lpSource = &ClipFormats[CF_OEMTEXT-1];
585 lpTarget = &ClipFormats[CF_UNICODETEXT-1];
586 foundData = TRUE;
587 TRACE("\tOEMTEXT -> UNICODETEXT\n");
590 if (!foundData)
592 if ((wFormat == CF_TEXT) || (wFormat == CF_OEMTEXT))
594 lpSource = &ClipFormats[CF_UNICODETEXT-1];
595 lpTarget = __lookup_format( ClipFormats, wFormat );
597 else
599 lpSource = __lookup_format( ClipFormats, wFormat );
600 lpTarget = lpSource;
604 /* First render the source text format */
605 if ( !lpSource || !CLIPBOARD_RenderFormat(lpSource) ) return NULL;
607 /* Convert to the desired target text format, if necessary */
608 if( lpTarget != lpSource && !lpTarget->hData16 && !lpTarget->hData32 )
610 INT src_chars, dst_chars, alloc_size;
611 LPCSTR lpstrS;
612 LPSTR lpstrT;
614 if (lpSource->hData32)
616 lpstrS = (LPSTR)GlobalLock(lpSource->hData32);
618 else
620 lpstrS = (LPSTR)GlobalLock16(lpSource->hData16);
623 if( !lpstrS ) return NULL;
625 /* Text always NULL terminated */
626 if(lpSource->wFormatID == CF_UNICODETEXT)
627 src_chars = strlenW((LPCWSTR)lpstrS)+1;
628 else
629 src_chars = strlen(lpstrS)+1;
631 /* Calculate number of characters in the destination buffer */
632 dst_chars = CLIPBOARD_ConvertText(lpSource->wFormatID, lpstrS, src_chars,
633 lpTarget->wFormatID, NULL, 0);
634 if(!dst_chars) return NULL;
636 TRACE("\tconverting from '%s' to '%s', %i chars\n",
637 lpSource->Name, lpTarget->Name, src_chars);
639 /* Convert characters to bytes */
640 if(lpTarget->wFormatID == CF_UNICODETEXT)
641 alloc_size = dst_chars * sizeof(WCHAR);
642 else
643 alloc_size = dst_chars;
645 lpTarget->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, alloc_size);
646 lpstrT = (LPSTR)GlobalLock(lpTarget->hData32);
648 if( lpstrT )
650 CLIPBOARD_ConvertText(lpSource->wFormatID, lpstrS, src_chars,
651 lpTarget->wFormatID, lpstrT, dst_chars);
652 GlobalUnlock(lpTarget->hData32);
654 else
655 lpTarget->hData32 = 0;
657 /* Unlock source */
658 if (lpSource->hData32)
659 GlobalUnlock(lpSource->hData32);
660 else
661 GlobalUnlock16(lpSource->hData16);
664 return (lpTarget->hData16 || lpTarget->hData32) ? lpTarget : NULL;
667 /**************************************************************************
668 * CLIPBOARD_EnumClipboardFormats (internal)
670 static UINT CLIPBOARD_EnumClipboardFormats( UINT wFormat )
672 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
673 BOOL bFormatPresent;
675 if (wFormat == 0) /* start from the beginning */
676 lpFormat = ClipFormats;
677 else
679 /* walk up to the specified format record */
681 if( !(lpFormat = __lookup_format( lpFormat, wFormat )) )
682 return 0;
683 lpFormat = lpFormat->NextFormat; /* right */
686 while(TRUE)
688 if (lpFormat == NULL) return 0;
690 if(CLIPBOARD_IsPresent(lpFormat->wFormatID))
691 break;
693 /* Query the driver if not yet in the cache */
694 if (!USER_Driver.pIsSelectionOwner())
696 if(lpFormat->wFormatID == CF_UNICODETEXT ||
697 lpFormat->wFormatID == CF_TEXT ||
698 lpFormat->wFormatID == CF_OEMTEXT)
700 if(USER_Driver.pIsClipboardFormatAvailable(CF_UNICODETEXT) ||
701 USER_Driver.pIsClipboardFormatAvailable(CF_TEXT) ||
702 USER_Driver.pIsClipboardFormatAvailable(CF_OEMTEXT))
703 bFormatPresent = TRUE;
704 else
705 bFormatPresent = FALSE;
707 else
708 bFormatPresent = USER_Driver.pIsClipboardFormatAvailable(lpFormat->wFormatID);
710 if(bFormatPresent)
711 break;
714 lpFormat = lpFormat->NextFormat;
717 TRACE("Next available format %d\n", lpFormat->wFormatID);
719 return lpFormat->wFormatID;
723 /**************************************************************************
724 * WIN32 Clipboard implementation
725 **************************************************************************/
727 /**************************************************************************
728 * OpenClipboard (USER32.@)
730 * Note: Netscape uses NULL hWnd to open the clipboard.
732 BOOL WINAPI OpenClipboard( HWND hWnd )
734 BOOL bRet;
736 TRACE("(%04x)...\n", hWnd);
738 if (!hClipLock)
740 hClipLock = GetCurrentTask();
742 /* Save current user of the clipboard */
743 hWndClipWindow = WIN_GetFullHandle( hWnd );
744 bCBHasChanged = FALSE;
745 bRet = TRUE;
747 else bRet = FALSE;
749 TRACE(" returning %i\n", bRet);
750 return bRet;
754 /**************************************************************************
755 * CloseClipboard (USER.138)
757 BOOL16 WINAPI CloseClipboard16(void)
759 return CloseClipboard();
763 /**************************************************************************
764 * CloseClipboard (USER32.@)
766 BOOL WINAPI CloseClipboard(void)
768 TRACE("()\n");
770 if (hClipLock == GetCurrentTask())
772 hWndClipWindow = 0;
774 if (bCBHasChanged && hWndViewer) SendMessageW( hWndViewer, WM_DRAWCLIPBOARD, 0, 0 );
775 hClipLock = 0;
777 return TRUE;
781 /**************************************************************************
782 * EmptyClipboard (USER.139)
784 BOOL16 WINAPI EmptyClipboard16(void)
786 return EmptyClipboard();
790 /**************************************************************************
791 * EmptyClipboard (USER32.@)
792 * Empties and acquires ownership of the clipboard
794 BOOL WINAPI EmptyClipboard(void)
796 TRACE("()\n");
798 if (hClipLock != GetCurrentTask())
800 WARN("Clipboard not opened by calling task!\n");
801 return FALSE;
804 /* destroy private objects */
806 if (hWndClipOwner) SendMessageW( hWndClipOwner, WM_DESTROYCLIPBOARD, 0, 0 );
808 /* empty the cache */
809 CLIPBOARD_EmptyCache(TRUE);
811 /* Assign ownership of the clipboard to the current client */
812 hWndClipOwner = hWndClipWindow;
814 /* Save the current task */
815 hTaskClipOwner = GetCurrentTask();
817 /* Tell the driver to acquire the selection */
818 USER_Driver.pAcquireClipboard();
820 return TRUE;
824 /**************************************************************************
825 * GetClipboardOwner (USER32.@)
826 * FIXME: Can't return the owner if the clipbard is owned by an external app
828 HWND WINAPI GetClipboardOwner(void)
830 TRACE("()\n");
831 return hWndClipOwner;
835 /**************************************************************************
836 * SetClipboardData (USER.141)
838 HANDLE16 WINAPI SetClipboardData16( UINT16 wFormat, HANDLE16 hData )
840 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
842 TRACE("(%04X, %04x) !\n", wFormat, hData);
844 /* NOTE: If the hData is zero and current owner doesn't match
845 * the window that opened the clipboard then this application
846 * is screwed because WM_RENDERFORMAT will go to the owner.
847 * (to become the owner it must call EmptyClipboard() before
848 * adding new data).
851 if( CLIPBOARD_IsLocked() || !lpFormat ||
852 (!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) )
854 WARN("Invalid hData or clipboard not opened by calling task!\n");
855 return 0;
858 /* Pass on the request to the driver */
859 USER_Driver.pSetClipboardData(wFormat);
861 if ( lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32 )
863 CLIPBOARD_DeleteRecord(lpFormat, TRUE);
865 /* delete existing CF_UNICODETEXT/CF_TEXT/CF_OEMTEXT aliases */
866 if(wFormat == CF_UNICODETEXT)
868 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
869 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
871 else if(wFormat == CF_TEXT)
873 CLIPBOARD_DeleteRecord(&ClipFormats[CF_UNICODETEXT-1], TRUE);
874 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
876 else if(wFormat == CF_OEMTEXT)
878 CLIPBOARD_DeleteRecord(&ClipFormats[CF_UNICODETEXT-1], TRUE);
879 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
883 bCBHasChanged = TRUE;
884 lpFormat->wDataPresent = 1;
885 lpFormat->hData16 = hData; /* 0 is legal, see WM_RENDERFORMAT */
886 lpFormat->hData32 = 0;
888 return lpFormat->hData16;
892 /**************************************************************************
893 * SetClipboardData (USER32.@)
895 HANDLE WINAPI SetClipboardData( UINT wFormat, HANDLE hData )
897 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
899 TRACE("(%08X, %08x) !\n", wFormat, hData);
901 /* NOTE: If the hData is zero and current owner doesn't match
902 * the window that opened the clipboard then this application
903 * is screwed because WM_RENDERFORMAT will go to the owner.
904 * (to become the owner it must call EmptyClipboard() before
905 * adding new data).
908 if( CLIPBOARD_IsLocked() || !lpFormat ||
909 (!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) )
911 WARN("Invalid hData or clipboard not opened by calling task!\n");
912 return 0;
915 /* Tell the driver to acquire the selection */
916 USER_Driver.pAcquireClipboard();
918 if ( lpFormat->wDataPresent &&
919 (lpFormat->hData16 || lpFormat->hData32) )
921 CLIPBOARD_DeleteRecord(lpFormat, TRUE);
923 /* delete existing CF_UNICODETEXT/CF_TEXT/CF_OEMTEXT aliases */
924 if(wFormat == CF_UNICODETEXT)
926 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
927 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
929 else if(wFormat == CF_TEXT)
931 CLIPBOARD_DeleteRecord(&ClipFormats[CF_UNICODETEXT-1], TRUE);
932 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
934 else if(wFormat == CF_OEMTEXT)
936 CLIPBOARD_DeleteRecord(&ClipFormats[CF_UNICODETEXT-1], TRUE);
937 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
941 bCBHasChanged = TRUE;
942 lpFormat->wDataPresent = 1;
943 lpFormat->hDataSrc32 = hData; /* Save the source handle */
946 * Make a shared duplicate if the memory is not shared
947 * TODO: What should be done for non-memory objects
949 if ( CLIPBOARD_IsMemoryObject(wFormat) && hData && !(GlobalFlags(hData) & GMEM_DDESHARE) )
950 lpFormat->hData32 = CLIPBOARD_GlobalDupMem( hData );
951 else
952 lpFormat->hData32 = hData; /* 0 is legal, see WM_RENDERFORMAT */
954 lpFormat->hData16 = 0;
956 return lpFormat->hData32; /* Should we return lpFormat->hDataSrc32 */
960 /**************************************************************************
961 * GetClipboardData (USER.142)
963 HANDLE16 WINAPI GetClipboardData16( UINT16 wFormat )
965 LPWINE_CLIPFORMAT lpRender = ClipFormats;
967 TRACE("(%04X)\n", wFormat);
969 if (CLIPBOARD_IsLocked())
971 WARN("Clipboard not opened by calling task!\n");
972 return 0;
975 if( wFormat == CF_UNICODETEXT || wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
977 lpRender = CLIPBOARD_RenderText(wFormat);
978 if ( !lpRender ) return 0;
980 else
982 lpRender = __lookup_format( ClipFormats, wFormat );
983 if( !lpRender || !CLIPBOARD_RenderFormat(lpRender) ) return 0;
986 /* Convert between 32 -> 16 bit data, if necessary */
987 if( lpRender->hData32 && !lpRender->hData16
988 && CLIPBOARD_IsMemoryObject(wFormat) )
990 int size;
991 if( lpRender->wFormatID == CF_METAFILEPICT )
992 size = sizeof( METAFILEPICT16 );
993 else
994 size = GlobalSize(lpRender->hData32);
996 lpRender->hData16 = GlobalAlloc16(GMEM_ZEROINIT, size);
997 if( !lpRender->hData16 )
998 ERR("(%04X) -- not enough memory in 16b heap\n", wFormat);
999 else
1001 if( lpRender->wFormatID == CF_METAFILEPICT )
1003 FIXME("\timplement function CopyMetaFilePict32to16\n");
1004 FIXME("\tin the appropriate file.\n");
1005 #ifdef SOMEONE_IMPLEMENTED_ME
1006 CopyMetaFilePict32to16( GlobalLock16(lpRender->hData16),
1007 GlobalLock(lpRender->hData32) );
1008 #endif
1010 else
1012 memcpy( GlobalLock16(lpRender->hData16),
1013 GlobalLock(lpRender->hData32),
1014 size );
1016 GlobalUnlock16(lpRender->hData16);
1017 GlobalUnlock(lpRender->hData32);
1021 TRACE("\treturning %04x (type %i)\n",
1022 lpRender->hData16, lpRender->wFormatID);
1023 return lpRender->hData16;
1027 /**************************************************************************
1028 * GetClipboardData (USER32.@)
1030 HANDLE WINAPI GetClipboardData( UINT wFormat )
1032 LPWINE_CLIPFORMAT lpRender = ClipFormats;
1034 TRACE("(%08X)\n", wFormat);
1036 if (CLIPBOARD_IsLocked())
1038 WARN("Clipboard not opened by calling task!\n");
1039 return 0;
1042 if( wFormat == CF_UNICODETEXT || wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
1044 lpRender = CLIPBOARD_RenderText(wFormat);
1045 if ( !lpRender ) return 0;
1047 else
1049 lpRender = __lookup_format( ClipFormats, wFormat );
1050 if( !lpRender || !CLIPBOARD_RenderFormat(lpRender) ) return 0;
1053 /* Convert between 16 -> 32 bit data, if necessary */
1054 if( lpRender->hData16 && !lpRender->hData32
1055 && CLIPBOARD_IsMemoryObject(wFormat) )
1057 int size;
1058 if( lpRender->wFormatID == CF_METAFILEPICT )
1059 size = sizeof( METAFILEPICT );
1060 else
1061 size = GlobalSize16(lpRender->hData16);
1062 lpRender->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE,
1063 size);
1064 if( lpRender->wFormatID == CF_METAFILEPICT )
1066 FIXME("\timplement function CopyMetaFilePict16to32\n");
1067 FIXME("\tin the appropriate file.\n");
1068 #ifdef SOMEONE_IMPLEMENTED_ME
1069 CopyMetaFilePict16to32( GlobalLock16(lpRender->hData32),
1070 GlobalLock(lpRender->hData16) );
1071 #endif
1073 else
1075 memcpy( GlobalLock(lpRender->hData32),
1076 GlobalLock16(lpRender->hData16),
1077 size );
1079 GlobalUnlock(lpRender->hData32);
1080 GlobalUnlock16(lpRender->hData16);
1083 TRACE("\treturning %04x (type %i)\n",
1084 lpRender->hData32, lpRender->wFormatID);
1085 return lpRender->hData32;
1089 /**************************************************************************
1090 * CountClipboardFormats (USER.143)
1092 INT16 WINAPI CountClipboardFormats16(void)
1094 return CountClipboardFormats();
1098 /**************************************************************************
1099 * CountClipboardFormats (USER32.@)
1101 INT WINAPI CountClipboardFormats(void)
1103 INT FormatCount = 0;
1104 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
1106 TRACE("()\n");
1108 while(TRUE)
1110 if (lpFormat == NULL) break;
1112 if( lpFormat->wFormatID != CF_TEXT ) /* Don't count CF_TEXT */
1115 * The format is available if either:
1116 * 1. The data is already in the cache.
1117 * 2. The selection is not owned by us(WINE) and the data is
1118 * available to the clipboard driver.
1120 if ( lpFormat->wDataPresent ||
1121 ( !USER_Driver.pIsSelectionOwner()
1122 && USER_Driver.pIsClipboardFormatAvailable( lpFormat->wFormatID ) ) )
1124 TRACE("\tdata found for format 0x%04x(%s)\n",
1125 lpFormat->wFormatID, CLIPBOARD_GetFormatName(lpFormat->wFormatID));
1126 FormatCount++;
1130 lpFormat = lpFormat->NextFormat;
1133 /* these are equivalent, adjust the total */
1134 FormatCount += (ClipFormats[CF_UNICODETEXT-1].wDataPresent ||
1135 ClipFormats[CF_TEXT-1].wDataPresent ||
1136 ClipFormats[CF_OEMTEXT-1].wDataPresent) ? 1 : 0;
1138 TRACE("\ttotal %d\n", FormatCount);
1139 return FormatCount;
1142 /**************************************************************************
1143 * EnumClipboardFormats (USER.144)
1145 UINT16 WINAPI EnumClipboardFormats16( UINT16 wFormat )
1147 return EnumClipboardFormats( wFormat );
1151 /**************************************************************************
1152 * EnumClipboardFormats (USER32.@)
1154 UINT WINAPI EnumClipboardFormats( UINT wFormat )
1156 TRACE("(%04X)\n", wFormat);
1158 if (CLIPBOARD_IsLocked())
1160 WARN("Clipboard not opened by calling task!\n");
1161 return 0;
1164 return CLIPBOARD_EnumClipboardFormats(wFormat);
1168 /**************************************************************************
1169 * RegisterClipboardFormatA (USER32.@)
1171 UINT WINAPI RegisterClipboardFormatA( LPCSTR FormatName )
1173 LPWINE_CLIPFORMAT lpNewFormat;
1174 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
1176 if (FormatName == NULL) return 0;
1178 TRACE("('%s') !\n", FormatName);
1180 /* walk format chain to see if it's already registered */
1182 while(TRUE)
1184 if ( !strcmp(lpFormat->Name,FormatName) )
1186 lpFormat->wRefCount++;
1187 return lpFormat->wFormatID;
1190 if ( lpFormat->NextFormat == NULL ) break;
1192 lpFormat = lpFormat->NextFormat;
1195 /* allocate storage for new format entry */
1197 lpNewFormat = (LPWINE_CLIPFORMAT)HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_CLIPFORMAT));
1198 if(lpNewFormat == NULL) {
1199 WARN("No more memory for a new format!\n");
1200 return 0;
1202 lpFormat->NextFormat = lpNewFormat;
1203 lpNewFormat->wFormatID = LastRegFormat;
1204 lpNewFormat->wRefCount = 1;
1206 if (!(lpNewFormat->Name = HeapAlloc(GetProcessHeap(), 0, strlen(FormatName)+1 )))
1208 WARN("No more memory for the new format name!\n");
1209 HeapFree(GetProcessHeap(), 0, lpNewFormat);
1210 return 0;
1212 strcpy( lpNewFormat->Name, FormatName );
1214 lpNewFormat->wDataPresent = 0;
1215 lpNewFormat->hData16 = 0;
1216 lpNewFormat->hDataSrc32 = 0;
1217 lpNewFormat->hData32 = 0;
1218 lpNewFormat->drvData = 0;
1219 lpNewFormat->PrevFormat = lpFormat;
1220 lpNewFormat->NextFormat = NULL;
1222 /* Pass on the registration request to the driver */
1223 USER_Driver.pRegisterClipboardFormat( FormatName );
1225 return LastRegFormat++;
1229 /**************************************************************************
1230 * RegisterClipboardFormat (USER.145)
1232 UINT16 WINAPI RegisterClipboardFormat16( LPCSTR FormatName )
1234 return RegisterClipboardFormatA( FormatName );
1238 /**************************************************************************
1239 * RegisterClipboardFormatW (USER32.@)
1241 UINT WINAPI RegisterClipboardFormatW( LPCWSTR formatName )
1243 LPSTR aFormat = HEAP_strdupWtoA( GetProcessHeap(), 0, formatName );
1244 UINT ret = RegisterClipboardFormatA( aFormat );
1245 HeapFree( GetProcessHeap(), 0, aFormat );
1246 return ret;
1250 /**************************************************************************
1251 * GetClipboardFormatName (USER.146)
1253 INT16 WINAPI GetClipboardFormatName16( UINT16 wFormat, LPSTR retStr, INT16 maxlen )
1255 return GetClipboardFormatNameA( wFormat, retStr, maxlen );
1259 /**************************************************************************
1260 * GetClipboardFormatNameA (USER32.@)
1262 INT WINAPI GetClipboardFormatNameA( UINT wFormat, LPSTR retStr, INT maxlen )
1264 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
1266 TRACE("(%04X, %p, %d) !\n", wFormat, retStr, maxlen);
1268 if (lpFormat == NULL || lpFormat->Name == NULL ||
1269 lpFormat->wFormatID < CF_REGFORMATBASE) return 0;
1271 TRACE("Name='%s' !\n", lpFormat->Name);
1273 lstrcpynA( retStr, lpFormat->Name, maxlen );
1274 return strlen(retStr);
1278 /**************************************************************************
1279 * GetClipboardFormatNameW (USER32.@)
1281 INT WINAPI GetClipboardFormatNameW( UINT wFormat, LPWSTR retStr, INT maxlen )
1283 INT ret;
1284 LPSTR p = HeapAlloc( GetProcessHeap(), 0, maxlen );
1285 if(p == NULL) return 0; /* FIXME: is this the correct failure value? */
1287 ret = GetClipboardFormatNameA( wFormat, p, maxlen );
1289 if (maxlen > 0 && !MultiByteToWideChar( CP_ACP, 0, p, -1, retStr, maxlen ))
1290 retStr[maxlen-1] = 0;
1291 HeapFree( GetProcessHeap(), 0, p );
1292 return ret;
1296 /**************************************************************************
1297 * SetClipboardViewer (USER32.@)
1299 HWND WINAPI SetClipboardViewer( HWND hWnd )
1301 HWND hwndPrev = hWndViewer;
1303 TRACE("(%04x): returning %04x\n", hWnd, hwndPrev);
1305 hWndViewer = WIN_GetFullHandle( hWnd );
1306 return hwndPrev;
1310 /**************************************************************************
1311 * GetClipboardViewer (USER32.@)
1313 HWND WINAPI GetClipboardViewer(void)
1315 TRACE("()\n");
1316 return hWndViewer;
1320 /**************************************************************************
1321 * ChangeClipboardChain (USER32.@)
1323 BOOL WINAPI ChangeClipboardChain(HWND hWnd, HWND hWndNext)
1325 BOOL bRet = 0;
1327 FIXME("(0x%04x, 0x%04x): stub?\n", hWnd, hWndNext);
1329 if( hWndViewer )
1330 bRet = !SendMessageW( hWndViewer, WM_CHANGECBCHAIN, (WPARAM)hWnd, (LPARAM)hWndNext );
1331 else
1332 WARN("hWndViewer is lost\n");
1334 if( WIN_GetFullHandle(hWnd) == hWndViewer ) hWndViewer = WIN_GetFullHandle( hWndNext );
1336 return bRet;
1340 /**************************************************************************
1341 * IsClipboardFormatAvailable (USER.193)
1343 BOOL16 WINAPI IsClipboardFormatAvailable16( UINT16 wFormat )
1345 return IsClipboardFormatAvailable( wFormat );
1349 /**************************************************************************
1350 * IsClipboardFormatAvailable (USER32.@)
1352 BOOL WINAPI IsClipboardFormatAvailable( UINT wFormat )
1354 BOOL bRet;
1356 if (wFormat == 0) /* Reject this case quickly */
1357 bRet = FALSE;
1358 else
1360 UINT iret = CLIPBOARD_EnumClipboardFormats(wFormat - 1);
1361 if ((wFormat == CF_TEXT) || (wFormat == CF_OEMTEXT) || (wFormat == CF_UNICODETEXT))
1362 bRet = ((iret == CF_TEXT) || (iret == CF_OEMTEXT) || (iret == CF_UNICODETEXT));
1363 else
1364 bRet = iret == wFormat;
1366 TRACE("(%04X)- ret(%d)\n", wFormat, bRet);
1367 return bRet;
1371 /**************************************************************************
1372 * GetOpenClipboardWindow (USER32.@)
1373 * FIXME: This wont work if an external app owns the selection
1375 HWND WINAPI GetOpenClipboardWindow(void)
1377 TRACE("()\n");
1378 return hWndClipWindow;
1382 /**************************************************************************
1383 * GetPriorityClipboardFormat (USER32.@)
1385 INT WINAPI GetPriorityClipboardFormat( UINT *list, INT nCount )
1387 int i;
1388 TRACE("()\n");
1390 if(CountClipboardFormats() == 0) return 0;
1392 for (i = 0; i < nCount; i++)
1393 if (IsClipboardFormatAvailable( list[i] )) return list[i];
1394 return -1;
1398 /**************************************************************************
1399 * GetClipboardSequenceNumber (USER32.@)
1400 * Supported on Win2k/Win98
1401 * MSDN: Windows clipboard code keeps a serial number for the clipboard
1402 * for each window station. The number is incremented whenever the
1403 * contents change or are emptied.
1404 * If you do not have WINSTA_ACCESSCLIPBOARD then the function returns 0
1406 DWORD WINAPI GetClipboardSequenceNumber(VOID)
1408 FIXME("Returning 0, see windows/clipboard.c\n");
1409 /* FIXME: Use serial numbers */
1410 return 0;