- Unixware (Solaris) linker typo fixed
[wine.git] / windows / clipboard.c
blob27fe04bb622a519621ca037f96824a721fd44aae
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 "winuser.h"
27 #include "wine/winuser16.h"
28 #include "wine/winbase16.h"
29 #include "heap.h"
30 #include "message.h"
31 #include "task.h"
32 #include "queue.h"
33 #include "clipboard.h"
34 #include "xmalloc.h"
35 #include "debugtools.h"
37 DEFAULT_DEBUG_CHANNEL(clipboard)
39 #define CF_REGFORMATBASE 0xC000
41 /**************************************************************************
42 * Clipboard context global variables
45 CLIPBOARD_DRIVER *CLIPBOARD_Driver = NULL;
47 static HANDLE hClipLock = 0;
48 static BOOL bCBHasChanged = FALSE;
50 HWND hWndClipWindow = 0; /* window that last opened clipboard */
51 HWND hWndClipOwner = 0; /* current clipboard owner */
52 HANDLE16 hTaskClipOwner = 0; /* clipboard owner's task */
53 static HWND hWndViewer = 0; /* start of viewers chain */
55 static WORD LastRegFormat = CF_REGFORMATBASE;
57 /* Clipboard cache initial data.
58 * WARNING: This data ordering is dependendent on the WINE_CLIPFORMAT structure
59 * declared in clipboard.h
61 WINE_CLIPFORMAT ClipFormats[16] = {
62 { CF_TEXT, 1, 0, "Text", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, NULL, &ClipFormats[1]},
63 { CF_BITMAP, 1, 0, "Bitmap", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[0], &ClipFormats[2]},
64 { CF_METAFILEPICT, 1, 0, "MetaFile Picture", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[1], &ClipFormats[3]},
65 { CF_SYLK, 1, 0, "Sylk", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[2], &ClipFormats[4]},
66 { CF_DIF, 1, 0, "DIF", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[3], &ClipFormats[5]},
67 { CF_TIFF, 1, 0, "TIFF", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[4], &ClipFormats[6]},
68 { CF_OEMTEXT, 1, 0, "OEM Text", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[5], &ClipFormats[7]},
69 { CF_DIB, 1, 0, "DIB", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[6], &ClipFormats[8]},
70 { CF_PALETTE, 1, 0, "Palette", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[7], &ClipFormats[9]},
71 { CF_PENDATA, 1, 0, "PenData", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[8], &ClipFormats[10]},
72 { CF_RIFF, 1, 0, "RIFF", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[9], &ClipFormats[11]},
73 { CF_WAVE, 1, 0, "Wave", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[10], &ClipFormats[12]},
74 { CF_OWNERDISPLAY, 1, 0, "Owner Display", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[11], &ClipFormats[13]},
75 { CF_DSPTEXT, 1, 0, "DSPText", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[12], &ClipFormats[14]},
76 { CF_DSPMETAFILEPICT, 1, 0, "DSPMetaFile Picture", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[13], &ClipFormats[15]},
77 { CF_DSPBITMAP, 1, 0, "DSPBitmap", (HANDLE16)NULL, (HANDLE)NULL, (HANDLE)NULL, 0, &ClipFormats[14], NULL}
81 /**************************************************************************
82 * Internal Clipboard implementation methods
83 **************************************************************************/
86 /**************************************************************************
87 * CLIPBOARD_LookupFormat
89 static LPWINE_CLIPFORMAT __lookup_format( LPWINE_CLIPFORMAT lpFormat, WORD wID )
91 while(TRUE)
93 if (lpFormat == NULL ||
94 lpFormat->wFormatID == wID) break;
95 lpFormat = lpFormat->NextFormat;
97 return lpFormat;
100 LPWINE_CLIPFORMAT CLIPBOARD_LookupFormat( WORD wID )
102 return __lookup_format( ClipFormats, wID );
105 /**************************************************************************
106 * CLIPBOARD_IsLocked
107 * Check if the clipboard cache is available to the caller
109 BOOL CLIPBOARD_IsLocked()
111 BOOL bIsLocked = TRUE;
112 HANDLE16 hTaskCur = GetCurrentTask();
115 * The clipboard is available:
116 * 1. if the caller's task has opened the clipboard,
117 * or
118 * 2. if the caller is the clipboard owners task, AND is responding to a
119 * WM_RENDERFORMAT message.
121 if ( hClipLock == hTaskCur )
122 bIsLocked = FALSE;
124 else if ( hTaskCur == hTaskClipOwner )
126 /* Check if we're currently executing inside a window procedure
127 * called in response to a WM_RENDERFORMAT message. A WM_RENDERFORMAT
128 * handler is not permitted to open the clipboard since it has been opened
129 * by another client. However the handler must have access to the
130 * clipboard in order to update data in response to this message.
132 MESSAGEQUEUE *queue = QUEUE_Lock( GetFastQueue16() );
134 if ( queue
135 && queue->smWaiting
136 && queue->smWaiting->msg == WM_RENDERFORMAT
137 && queue->smWaiting->hSrcQueue
139 bIsLocked = FALSE;
141 QUEUE_Unlock( queue );
144 return bIsLocked;
147 /**************************************************************************
148 * CLIPBOARD_ReleaseOwner
149 * Gives up ownership of the clipboard
151 void CLIPBOARD_ReleaseOwner()
153 hWndClipOwner = 0;
154 hTaskClipOwner = 0;
157 /**************************************************************************
158 * CLIPBOARD_GlobalFreeProc
160 * This is a callback mechanism to allow HGLOBAL data to be released in
161 * the context of the process which allocated it. We post a WM_TIMER message
162 * to the owner window(in CLIPBOARD_DeleteRecord) and destroy the data(in idEvent)
163 * in this WndProc, which is invoked when the apps message loop calls DispatchMessage.
164 * This technique is discussed in Matt Pietrek's "Under the Hood".
165 * An article describing the same may be found in MSDN by searching for WM_TIMER.
166 * Note that this mechanism will probably stop working when WINE supports
167 * address space separation. When "queue events" are implemented in Wine we
168 * should switch to using that mechanism, since it is more robust and does not
169 * require a procedure address to be passed. See the SetWinEventHook API for
170 * more info on this.
172 VOID CALLBACK CLIPBOARD_GlobalFreeProc( HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime )
174 /* idEvent is the HGLOBAL to be deleted */
175 GlobalFree( (HGLOBAL)idEvent );
178 /**************************************************************************
179 * CLIPBOARD_DeleteRecord
181 void CLIPBOARD_DeleteRecord(LPWINE_CLIPFORMAT lpFormat, BOOL bChange)
183 if( (lpFormat->wFormatID >= CF_GDIOBJFIRST &&
184 lpFormat->wFormatID <= CF_GDIOBJLAST) || lpFormat->wFormatID == CF_BITMAP
185 || lpFormat->wFormatID == CF_PALETTE)
187 if (lpFormat->hData32)
188 DeleteObject(lpFormat->hData32);
189 if (lpFormat->hData16)
190 DeleteObject16(lpFormat->hData16);
192 else if( lpFormat->wFormatID == CF_METAFILEPICT )
194 if (lpFormat->hData32)
196 DeleteMetaFile( ((METAFILEPICT *)GlobalLock( lpFormat->hData32 ))->hMF );
197 PostMessageA(hWndClipOwner, WM_TIMER,
198 (WPARAM)lpFormat->hData32, (LPARAM)CLIPBOARD_GlobalFreeProc);
199 if (lpFormat->hDataSrc32)
201 /* Release lpFormat->hData32 in the context of the process which created it.
202 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
203 * GlobalFree(lpFormat->hDataSrc32);
205 PostMessageA(hWndClipOwner, WM_TIMER,
206 (WPARAM)lpFormat->hDataSrc32, (LPARAM)CLIPBOARD_GlobalFreeProc);
209 if (lpFormat->hData16)
210 /* HMETAFILE16 and HMETAFILE32 are apparently the same thing,
211 and a shallow copy is enough to share a METAFILEPICT
212 structure between 16bit and 32bit clipboards. The MetaFile
213 should of course only be deleted once. */
214 GlobalFree16(lpFormat->hData16);
216 if (lpFormat->hData16)
218 DeleteMetaFile16( ((METAFILEPICT16 *)GlobalLock16( lpFormat->hData16 ))->hMF );
219 GlobalFree16(lpFormat->hData16);
222 else
224 if (lpFormat->hData32)
226 /* Release lpFormat->hData32 in the context of the process which created it.
227 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
228 * GlobalFree( lpFormat->hData32 );
230 PostMessageA(hWndClipOwner, WM_TIMER,
231 (WPARAM)lpFormat->hData32, (LPARAM)CLIPBOARD_GlobalFreeProc);
233 if (lpFormat->hDataSrc32)
235 /* Release lpFormat->hData32 in the context of the process which created it.
236 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
237 * GlobalFree(lpFormat->hDataSrc32);
239 PostMessageA(hWndClipOwner, WM_TIMER,
240 (WPARAM)lpFormat->hDataSrc32, (LPARAM)CLIPBOARD_GlobalFreeProc);
242 if (lpFormat->hData16)
243 GlobalFree16(lpFormat->hData16);
246 lpFormat->wDataPresent = 0;
247 lpFormat->hData16 = 0;
248 lpFormat->hData32 = 0;
249 lpFormat->hDataSrc32 = 0;
250 lpFormat->drvData = 0;
252 if( bChange ) bCBHasChanged = TRUE;
255 /**************************************************************************
256 * CLIPBOARD_EmptyCache
258 void CLIPBOARD_EmptyCache( BOOL bChange )
260 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
262 while(lpFormat)
264 if ( lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32 )
265 CLIPBOARD_DeleteRecord( lpFormat, bChange );
267 lpFormat = lpFormat->NextFormat;
271 /**************************************************************************
272 * CLIPBOARD_IsPresent
274 BOOL CLIPBOARD_IsPresent(WORD wFormat)
276 /* special case */
278 if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
279 return ClipFormats[CF_TEXT-1].wDataPresent ||
280 ClipFormats[CF_OEMTEXT-1].wDataPresent;
281 else
283 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
284 if( lpFormat ) return (lpFormat->wDataPresent);
286 return FALSE;
289 /**************************************************************************
290 * CLIPBOARD_IsCacheRendered
291 * Checks if any data needs to be rendered to the clipboard cache
292 * RETURNS:
293 * TRUE - All clipboard data is available in the cache
294 * FALSE - Some data is marked for delayed render and needs rendering
296 BOOL CLIPBOARD_IsCacheRendered()
298 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
300 /* check if all formats were rendered */
301 while(lpFormat)
303 if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
304 return FALSE;
306 lpFormat = lpFormat->NextFormat;
309 return TRUE;
313 /**************************************************************************
314 * CLIPBOARD_IsMemoryObject
315 * Tests if the clipboard format specifies a memory object
317 BOOL CLIPBOARD_IsMemoryObject( WORD wFormat )
319 switch(wFormat)
321 case CF_BITMAP:
322 case CF_METAFILEPICT:
323 case CF_DSPTEXT:
324 case CF_ENHMETAFILE:
325 case CF_HDROP:
326 case CF_PALETTE:
327 case CF_PENDATA:
328 return FALSE;
329 default:
330 return TRUE;
334 /***********************************************************************
335 * CLIPBOARD_GlobalDupMem( HGLOBAL )
336 * Helper method to duplicate an HGLOBAL chunk of memory into shared memory
338 HGLOBAL CLIPBOARD_GlobalDupMem( HGLOBAL hGlobalSrc )
340 HGLOBAL hGlobalDest;
341 PVOID pGlobalSrc, pGlobalDest;
342 DWORD cBytes;
344 if ( !hGlobalSrc )
345 return 0;
347 cBytes = GlobalSize(hGlobalSrc);
348 if ( 0 == cBytes )
349 return 0;
351 /* Turn on the DDESHARE and _MOVEABLE flags explicitly */
352 hGlobalDest = GlobalAlloc( GlobalFlags(hGlobalSrc) | GMEM_DDESHARE | GMEM_MOVEABLE,
353 cBytes );
354 if ( !hGlobalDest )
355 return 0;
357 pGlobalSrc = GlobalLock(hGlobalSrc);
358 pGlobalDest = GlobalLock(hGlobalDest);
359 if ( !pGlobalSrc || !pGlobalDest )
360 return 0;
362 memcpy(pGlobalDest, pGlobalSrc, cBytes);
364 GlobalUnlock(hGlobalSrc);
365 GlobalUnlock(hGlobalDest);
367 return hGlobalDest;
370 /**************************************************************************
371 * CLIPBOARD_GetFormatName
372 * Gets the format name associated with an ID
374 char * CLIPBOARD_GetFormatName(UINT wFormat)
376 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
377 return (lpFormat) ? lpFormat->Name : NULL;
381 /**************************************************************************
382 * CLIPBOARD_RenderFormat
384 static BOOL CLIPBOARD_RenderFormat(LPWINE_CLIPFORMAT lpFormat)
387 * If WINE is not the selection owner, and the format is available
388 * we must ask the the driver to render the data to the clipboard cache.
390 if ( !CLIPBOARD_Driver->pIsSelectionOwner()
391 && CLIPBOARD_Driver->pIsFormatAvailable( lpFormat->wFormatID ) )
393 if ( !CLIPBOARD_Driver->pGetData( lpFormat->wFormatID ) )
394 return FALSE;
397 * If Wine owns the clipboard, and the data is marked for delayed render,
398 * render it now.
400 else if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
402 if( IsWindow(hWndClipOwner) )
404 /* Send a WM_RENDERFORMAT message to notify the owner to render the
405 * data requested into the clipboard.
407 TRACE("Sending WM_RENDERFORMAT message\n");
408 SendMessage16(hWndClipOwner,WM_RENDERFORMAT,
409 (WPARAM16)lpFormat->wFormatID,0L);
411 else
413 WARN("\thWndClipOwner (%04x) is lost!\n",
414 hWndClipOwner);
415 CLIPBOARD_ReleaseOwner();
416 lpFormat->wDataPresent = 0;
417 return FALSE;
421 return (lpFormat->hData16 || lpFormat->hData32) ? TRUE : FALSE;
425 /**************************************************************************
426 * CLIPBOARD_RenderText
428 * Renders text to the clipboard buffer converting between UNIX and DOS formats.
430 * RETURNS: pointer to the WINE_CLIPFORMAT if successful, NULL otherwise
432 * FIXME: Should be a pair of driver functions that convert between OEM text and Windows.
435 static LPWINE_CLIPFORMAT CLIPBOARD_RenderText( UINT wFormat )
437 LPWINE_CLIPFORMAT lpSource = ClipFormats;
438 LPWINE_CLIPFORMAT lpTarget;
440 /* Asked for CF_TEXT and not available - always attempt to convert from CF_OEM_TEXT */
441 if( wFormat == CF_TEXT && !ClipFormats[CF_TEXT-1].wDataPresent )
443 /* Convert OEMTEXT -> TEXT */
444 lpSource = &ClipFormats[CF_OEMTEXT-1];
445 lpTarget = &ClipFormats[CF_TEXT-1];
447 TRACE("\tOEMTEXT -> TEXT\n");
449 /* Asked for CF_OEM_TEXT, and CF_TEXT available */
450 else if( wFormat == CF_OEMTEXT && !ClipFormats[CF_OEMTEXT-1].wDataPresent
451 && ClipFormats[CF_TEXT-1].wDataPresent )
453 /* Convert TEXT -> OEMTEXT */
454 lpSource = &ClipFormats[CF_TEXT-1];
455 lpTarget = &ClipFormats[CF_OEMTEXT-1];
457 TRACE("\tTEXT -> OEMTEXT\n");
459 /* Text format requested is available - no conversion necessary */
460 else
462 lpSource = __lookup_format( ClipFormats, wFormat );
463 lpTarget = lpSource;
466 /* First render the source text format */
467 if ( !lpSource || !CLIPBOARD_RenderFormat(lpSource) ) return NULL;
469 /* Convert to the desired target text format, if necessary */
470 if( lpTarget != lpSource && !lpTarget->hData16 && !lpTarget->hData32 )
472 UINT16 size;
473 LPCSTR lpstrS;
474 LPSTR lpstrT;
476 if (lpSource->hData32)
478 size = GlobalSize( lpSource->hData32 );
479 lpstrS = (LPSTR)GlobalLock(lpSource->hData32);
481 else
483 size = GlobalSize16( lpSource->hData16 );
484 lpstrS = (LPSTR)GlobalLock16(lpSource->hData16);
487 if( !lpstrS ) return NULL;
488 TRACE("\tconverting from '%s' to '%s', %i chars\n",
489 lpSource->Name, lpTarget->Name, size);
491 lpTarget->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, size);
492 lpstrT = (LPSTR)GlobalLock(lpTarget->hData32);
494 if( lpstrT )
496 if( lpSource->wFormatID == CF_TEXT )
497 CharToOemBuffA(lpstrS, lpstrT, size);
498 else
499 OemToCharBuffA(lpstrS, lpstrT, size);
500 TRACE("\tgot %s\n", lpstrT);
501 GlobalUnlock(lpTarget->hData32);
503 else
504 lpTarget->hData32 = 0;
506 /* Unlock source */
507 if (lpSource->hData32)
508 GlobalUnlock(lpSource->hData32);
509 else
510 GlobalUnlock16(lpSource->hData16);
513 return (lpTarget->hData16 || lpTarget->hData32) ? lpTarget : NULL;
516 /**************************************************************************
517 * WIN32 Clipboard implementation
518 **************************************************************************/
520 /**************************************************************************
521 * OpenClipboard16 (USER.137)
523 BOOL16 WINAPI OpenClipboard16( HWND16 hWnd )
525 return OpenClipboard( hWnd );
529 /**************************************************************************
530 * OpenClipboard32 (USER32.407)
532 * Note: Netscape uses NULL hWnd to open the clipboard.
534 BOOL WINAPI OpenClipboard( HWND hWnd )
536 BOOL bRet;
538 TRACE("(%04x)...\n", hWnd);
540 if (!hClipLock)
542 hClipLock = GetCurrentTask();
544 /* Save current user of the clipboard */
545 hWndClipWindow = hWnd;
546 bCBHasChanged = FALSE;
547 bRet = TRUE;
549 else bRet = FALSE;
551 TRACE(" returning %i\n", bRet);
552 return bRet;
556 /**************************************************************************
557 * CloseClipboard16 (USER.138)
559 BOOL16 WINAPI CloseClipboard16(void)
561 return CloseClipboard();
565 /**************************************************************************
566 * CloseClipboard32 (USER32.54)
568 BOOL WINAPI CloseClipboard(void)
570 TRACE("()\n");
572 if (hClipLock == GetCurrentTask())
574 hWndClipWindow = 0;
576 if (bCBHasChanged && hWndViewer)
577 SendMessage16(hWndViewer, WM_DRAWCLIPBOARD, 0, 0L);
578 hClipLock = 0;
580 return TRUE;
584 /**************************************************************************
585 * EmptyClipboard16 (USER.139)
587 BOOL16 WINAPI EmptyClipboard16(void)
589 return EmptyClipboard();
593 /**************************************************************************
594 * EmptyClipboard32 (USER32.169)
595 * Empties and acquires ownership of the clipboard
597 BOOL WINAPI EmptyClipboard(void)
599 TRACE("()\n");
601 if (hClipLock != GetCurrentTask())
603 WARN("Clipboard not opened by calling task!");
604 return FALSE;
607 /* destroy private objects */
609 if (hWndClipOwner)
610 SendMessage16(hWndClipOwner, WM_DESTROYCLIPBOARD, 0, 0L);
612 /* empty the cache */
613 CLIPBOARD_EmptyCache(TRUE);
615 /* Assign ownership of the clipboard to the current client */
616 hWndClipOwner = hWndClipWindow;
618 /* Save the current task */
619 hTaskClipOwner = GetCurrentTask();
621 /* Tell the driver to acquire the selection */
622 CLIPBOARD_Driver->pAcquire();
624 return TRUE;
628 /**************************************************************************
629 * GetClipboardOwner16 (USER.140)
630 * FIXME: Can't return the owner if the clipbard is owned by an external app
632 HWND16 WINAPI GetClipboardOwner16(void)
634 TRACE("()\n");
635 return hWndClipOwner;
639 /**************************************************************************
640 * GetClipboardOwner32 (USER32.225)
641 * FIXME: Can't return the owner if the clipbard is owned by an external app
643 HWND WINAPI GetClipboardOwner(void)
645 TRACE("()\n");
646 return hWndClipOwner;
650 /**************************************************************************
651 * SetClipboardData16 (USER.141)
653 HANDLE16 WINAPI SetClipboardData16( UINT16 wFormat, HANDLE16 hData )
655 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
657 TRACE("(%04X, %04x) !\n", wFormat, hData);
659 /* NOTE: If the hData is zero and current owner doesn't match
660 * the window that opened the clipboard then this application
661 * is screwed because WM_RENDERFORMAT will go to the owner.
662 * (to become the owner it must call EmptyClipboard() before
663 * adding new data).
666 if( CLIPBOARD_IsLocked() || !lpFormat ||
667 (!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) )
669 WARN("Invalid hData or clipboard not opened by calling task!");
670 return 0;
673 /* Pass on the request to the driver */
674 CLIPBOARD_Driver->pSetData(wFormat);
676 if ( lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32 )
678 CLIPBOARD_DeleteRecord(lpFormat, TRUE);
680 /* delete existing CF_TEXT/CF_OEMTEXT aliases */
682 if( wFormat == CF_TEXT
683 && ( ClipFormats[CF_OEMTEXT-1].hData16
684 || ClipFormats[CF_OEMTEXT-1].hData32 )
685 && !ClipFormats[CF_OEMTEXT-1].wDataPresent )
686 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
687 if( wFormat == CF_OEMTEXT
688 && ( ClipFormats[CF_OEMTEXT-1].hData16
689 || ClipFormats[CF_OEMTEXT-1].hData32 )
690 && !ClipFormats[CF_TEXT-1].wDataPresent )
691 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
694 bCBHasChanged = TRUE;
695 lpFormat->wDataPresent = 1;
696 lpFormat->hData16 = hData; /* 0 is legal, see WM_RENDERFORMAT */
697 lpFormat->hData32 = 0;
699 return lpFormat->hData16;
703 /**************************************************************************
704 * SetClipboardData (USER32.470)
706 HANDLE WINAPI SetClipboardData( UINT wFormat, HANDLE hData )
708 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
710 TRACE("(%08X, %08x) !\n", wFormat, hData);
712 /* NOTE: If the hData is zero and current owner doesn't match
713 * the window that opened the clipboard then this application
714 * is screwed because WM_RENDERFORMAT will go to the owner.
715 * (to become the owner it must call EmptyClipboard() before
716 * adding new data).
719 if( CLIPBOARD_IsLocked() || !lpFormat ||
720 (!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) )
722 WARN("Invalid hData or clipboard not opened by calling task!");
723 return 0;
726 /* Tell the driver to acquire the selection */
727 CLIPBOARD_Driver->pAcquire();
729 if ( lpFormat->wDataPresent &&
730 (lpFormat->hData16 || lpFormat->hData32) )
732 CLIPBOARD_DeleteRecord(lpFormat, TRUE);
734 /* delete existing CF_TEXT/CF_OEMTEXT aliases */
736 if( wFormat == CF_TEXT
737 && ( ClipFormats[CF_OEMTEXT-1].hData16
738 || ClipFormats[CF_OEMTEXT-1].hData32 )
739 && !ClipFormats[CF_OEMTEXT-1].wDataPresent )
740 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
741 if( wFormat == CF_OEMTEXT
742 && ( ClipFormats[CF_OEMTEXT-1].hData16
743 || ClipFormats[CF_OEMTEXT-1].hData32 )
744 && !ClipFormats[CF_TEXT-1].wDataPresent )
745 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
748 bCBHasChanged = TRUE;
749 lpFormat->wDataPresent = 1;
750 lpFormat->hDataSrc32 = hData; /* Save the source handle */
753 * Make a shared duplicate if the memory is not shared
754 * TODO: What should be done for non-memory objects
756 if ( CLIPBOARD_IsMemoryObject(wFormat) && hData && !(GlobalFlags(hData) & GMEM_DDESHARE) )
757 lpFormat->hData32 = CLIPBOARD_GlobalDupMem( hData );
758 else
759 lpFormat->hData32 = hData; /* 0 is legal, see WM_RENDERFORMAT */
761 lpFormat->hData16 = 0;
763 return lpFormat->hData32; /* Should we return lpFormat->hDataSrc32 */
767 /**************************************************************************
768 * GetClipboardData16 (USER.142)
770 HANDLE16 WINAPI GetClipboardData16( UINT16 wFormat )
772 LPWINE_CLIPFORMAT lpRender = ClipFormats;
774 TRACE("(%04X)\n", wFormat);
776 if (CLIPBOARD_IsLocked())
778 WARN("Clipboard not opened by calling task!");
779 return 0;
782 if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
784 lpRender = CLIPBOARD_RenderText(wFormat);
785 if ( !lpRender ) return 0;
787 else
789 lpRender = __lookup_format( ClipFormats, wFormat );
790 if( !lpRender || !CLIPBOARD_RenderFormat(lpRender) ) return 0;
793 /* Convert between 32 -> 16 bit data, if necessary */
794 if( lpRender->hData32 && !lpRender->hData16
795 && CLIPBOARD_IsMemoryObject(wFormat) )
797 int size;
798 if( lpRender->wFormatID == CF_METAFILEPICT )
799 size = sizeof( METAFILEPICT16 );
800 else
801 size = GlobalSize(lpRender->hData32);
803 lpRender->hData16 = GlobalAlloc16(GMEM_ZEROINIT, size);
804 if( !lpRender->hData16 )
805 ERR("(%04X) -- not enough memory in 16b heap\n", wFormat);
806 else
808 if( lpRender->wFormatID == CF_METAFILEPICT )
810 FIXME("\timplement function CopyMetaFilePict32to16\n");
811 FIXME("\tin the appropriate file.\n");
812 #ifdef SOMEONE_IMPLEMENTED_ME
813 CopyMetaFilePict32to16( GlobalLock16(lpRender->hData16),
814 GlobalLock(lpRender->hData32) );
815 #endif
817 else
819 memcpy( GlobalLock16(lpRender->hData16),
820 GlobalLock(lpRender->hData32),
821 size );
823 GlobalUnlock16(lpRender->hData16);
824 GlobalUnlock(lpRender->hData32);
828 TRACE("\treturning %04x (type %i)\n",
829 lpRender->hData16, lpRender->wFormatID);
830 return lpRender->hData16;
834 /**************************************************************************
835 * GetClipboardData32 (USER32.222)
837 HANDLE WINAPI GetClipboardData( UINT wFormat )
839 LPWINE_CLIPFORMAT lpRender = ClipFormats;
841 TRACE("(%08X)\n", wFormat);
843 if (CLIPBOARD_IsLocked())
845 WARN("Clipboard not opened by calling task!");
846 return 0;
849 if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
851 lpRender = CLIPBOARD_RenderText(wFormat);
852 if ( !lpRender ) return 0;
854 else
856 lpRender = __lookup_format( ClipFormats, wFormat );
857 if( !lpRender || !CLIPBOARD_RenderFormat(lpRender) ) return 0;
860 /* Convert between 16 -> 32 bit data, if necessary */
861 if( lpRender->hData16 && !lpRender->hData32
862 && CLIPBOARD_IsMemoryObject(wFormat) )
864 int size;
865 if( lpRender->wFormatID == CF_METAFILEPICT )
866 size = sizeof( METAFILEPICT );
867 else
868 size = GlobalSize16(lpRender->hData16);
869 lpRender->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE,
870 size);
871 if( lpRender->wFormatID == CF_METAFILEPICT )
873 FIXME("\timplement function CopyMetaFilePict16to32\n");
874 FIXME("\tin the appropriate file.\n");
875 #ifdef SOMEONE_IMPLEMENTED_ME
876 CopyMetaFilePict16to32( GlobalLock16(lpRender->hData32),
877 GlobalLock(lpRender->hData16) );
878 #endif
880 else
882 memcpy( GlobalLock(lpRender->hData32),
883 GlobalLock16(lpRender->hData16),
884 size );
886 GlobalUnlock(lpRender->hData32);
887 GlobalUnlock16(lpRender->hData16);
890 TRACE("\treturning %04x (type %i)\n",
891 lpRender->hData32, lpRender->wFormatID);
892 return lpRender->hData32;
896 /**************************************************************************
897 * CountClipboardFormats16 (USER.143)
899 INT16 WINAPI CountClipboardFormats16(void)
901 return CountClipboardFormats();
905 /**************************************************************************
906 * CountClipboardFormats32 (USER32.63)
908 INT WINAPI CountClipboardFormats(void)
910 INT FormatCount = 0;
911 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
913 TRACE("()\n");
915 while(TRUE)
917 if (lpFormat == NULL) break;
919 if( lpFormat->wFormatID != CF_TEXT ) /* Don't count CF_TEXT */
922 * The format is available if either:
923 * 1. The data is already in the cache.
924 * 2. The selection is not owned by us(WINE) and the data is
925 * available to the clipboard driver.
927 if ( lpFormat->wDataPresent ||
928 ( !CLIPBOARD_Driver->pIsSelectionOwner()
929 && CLIPBOARD_Driver->pIsFormatAvailable( lpFormat->wFormatID ) ) )
931 TRACE("\tdata found for format %i(%s)\n",
932 lpFormat->wFormatID, CLIPBOARD_GetFormatName(lpFormat->wFormatID));
933 FormatCount++;
937 lpFormat = lpFormat->NextFormat;
940 /* these two are equivalent, adjust the total */
942 FormatCount += abs(ClipFormats[CF_TEXT-1].wDataPresent -
943 ClipFormats[CF_OEMTEXT-1].wDataPresent);
945 TRACE("\ttotal %d\n", FormatCount);
946 return FormatCount;
950 /**************************************************************************
951 * EnumClipboardFormats16 (USER.144)
953 UINT16 WINAPI EnumClipboardFormats16( UINT16 wFormat )
955 return EnumClipboardFormats( wFormat );
959 /**************************************************************************
960 * EnumClipboardFormats32 (USER32.179)
962 UINT WINAPI EnumClipboardFormats( UINT wFormat )
964 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
965 BOOL bFormatPresent;
967 TRACE("(%04X)\n", wFormat);
969 if (CLIPBOARD_IsLocked())
971 WARN("Clipboard not opened by calling task!");
972 return 0;
975 if (wFormat == 0) /* start from the beginning */
976 lpFormat = ClipFormats;
977 else
979 /* walk up to the specified format record */
981 if( !(lpFormat = __lookup_format( lpFormat, wFormat )) )
982 return 0;
983 lpFormat = lpFormat->NextFormat; /* right */
986 while(TRUE)
988 if (lpFormat == NULL) return 0;
990 /* Synthesize CF_TEXT from CF_OEMTEXT and vice versa */
991 bFormatPresent = (lpFormat->wDataPresent ||
992 (lpFormat->wFormatID == CF_OEMTEXT && ClipFormats[CF_TEXT-1].wDataPresent) ||
993 (lpFormat->wFormatID == CF_TEXT && ClipFormats[CF_OEMTEXT-1].wDataPresent) );
995 /* Query the driver if not yet in the cache */
996 if (!bFormatPresent && !CLIPBOARD_Driver->pIsSelectionOwner())
998 bFormatPresent =
999 CLIPBOARD_Driver->pIsFormatAvailable( (lpFormat->wFormatID == CF_TEXT) ?
1000 CF_OEMTEXT : lpFormat->wFormatID );
1003 if (bFormatPresent)
1004 break;
1006 lpFormat = lpFormat->NextFormat;
1009 return lpFormat->wFormatID;
1013 /**************************************************************************
1014 * RegisterClipboardFormat16 (USER.145)
1016 UINT16 WINAPI RegisterClipboardFormat16( LPCSTR FormatName )
1018 LPWINE_CLIPFORMAT lpNewFormat;
1019 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
1021 if (FormatName == NULL) return 0;
1023 TRACE("('%s') !\n", FormatName);
1025 /* walk format chain to see if it's already registered */
1027 while(TRUE)
1029 if ( !strcmp(lpFormat->Name,FormatName) )
1031 lpFormat->wRefCount++;
1032 return lpFormat->wFormatID;
1035 if ( lpFormat->NextFormat == NULL ) break;
1037 lpFormat = lpFormat->NextFormat;
1040 /* allocate storage for new format entry */
1042 lpNewFormat = (LPWINE_CLIPFORMAT)xmalloc(sizeof(WINE_CLIPFORMAT));
1043 lpFormat->NextFormat = lpNewFormat;
1044 lpNewFormat->wFormatID = LastRegFormat;
1045 lpNewFormat->wRefCount = 1;
1047 lpNewFormat->Name = (LPSTR)xmalloc(strlen(FormatName) + 1);
1048 strcpy(lpNewFormat->Name, FormatName);
1050 lpNewFormat->wDataPresent = 0;
1051 lpNewFormat->hData16 = 0;
1052 lpNewFormat->hDataSrc32 = 0;
1053 lpNewFormat->hData32 = 0;
1054 lpNewFormat->drvData = 0;
1055 lpNewFormat->PrevFormat = lpFormat;
1056 lpNewFormat->NextFormat = NULL;
1058 /* Pass on the registration request to the driver */
1059 CLIPBOARD_Driver->pRegisterFormat( FormatName );
1061 return LastRegFormat++;
1065 /**************************************************************************
1066 * RegisterClipboardFormat32A (USER32.431)
1068 UINT WINAPI RegisterClipboardFormatA( LPCSTR formatName )
1070 return RegisterClipboardFormat16( formatName );
1074 /**************************************************************************
1075 * RegisterClipboardFormat32W (USER32.432)
1077 UINT WINAPI RegisterClipboardFormatW( LPCWSTR formatName )
1079 LPSTR aFormat = HEAP_strdupWtoA( GetProcessHeap(), 0, formatName );
1080 UINT ret = RegisterClipboardFormatA( aFormat );
1081 HeapFree( GetProcessHeap(), 0, aFormat );
1082 return ret;
1086 /**************************************************************************
1087 * GetClipboardFormatName16 (USER.146)
1089 INT16 WINAPI GetClipboardFormatName16( UINT16 wFormat, LPSTR retStr, INT16 maxlen )
1091 return GetClipboardFormatNameA( wFormat, retStr, maxlen );
1095 /**************************************************************************
1096 * GetClipboardFormatName32A (USER32.223)
1098 INT WINAPI GetClipboardFormatNameA( UINT wFormat, LPSTR retStr, INT maxlen )
1100 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
1102 TRACE("(%04X, %p, %d) !\n", wFormat, retStr, maxlen);
1104 if (lpFormat == NULL || lpFormat->Name == NULL ||
1105 lpFormat->wFormatID < CF_REGFORMATBASE) return 0;
1107 TRACE("Name='%s' !\n", lpFormat->Name);
1109 lstrcpynA( retStr, lpFormat->Name, maxlen );
1110 return strlen(retStr);
1114 /**************************************************************************
1115 * GetClipboardFormatName32W (USER32.224)
1117 INT WINAPI GetClipboardFormatNameW( UINT wFormat, LPWSTR retStr, INT maxlen )
1119 LPSTR p = HEAP_xalloc( GetProcessHeap(), 0, maxlen );
1120 INT ret = GetClipboardFormatNameA( wFormat, p, maxlen );
1121 lstrcpynAtoW( retStr, p, maxlen );
1122 HeapFree( GetProcessHeap(), 0, p );
1123 return ret;
1127 /**************************************************************************
1128 * SetClipboardViewer16 (USER.147)
1130 HWND16 WINAPI SetClipboardViewer16( HWND16 hWnd )
1132 TRACE("(%04x)\n", hWnd);
1133 return SetClipboardViewer( hWnd );
1137 /**************************************************************************
1138 * SetClipboardViewer32 (USER32.471)
1140 HWND WINAPI SetClipboardViewer( HWND hWnd )
1142 HWND hwndPrev = hWndViewer;
1144 TRACE("(%04x): returning %04x\n", hWnd, hwndPrev);
1146 hWndViewer = hWnd;
1147 return hwndPrev;
1151 /**************************************************************************
1152 * GetClipboardViewer16 (USER.148)
1154 HWND16 WINAPI GetClipboardViewer16(void)
1156 TRACE("()\n");
1157 return hWndViewer;
1161 /**************************************************************************
1162 * GetClipboardViewer32 (USER32.226)
1164 HWND WINAPI GetClipboardViewer(void)
1166 TRACE("()\n");
1167 return hWndViewer;
1171 /**************************************************************************
1172 * ChangeClipboardChain16 (USER.149)
1174 BOOL16 WINAPI ChangeClipboardChain16(HWND16 hWnd, HWND16 hWndNext)
1176 return ChangeClipboardChain(hWnd, hWndNext);
1180 /**************************************************************************
1181 * ChangeClipboardChain32 (USER32.22)
1183 BOOL WINAPI ChangeClipboardChain(HWND hWnd, HWND hWndNext)
1185 BOOL bRet = 0;
1187 FIXME("(0x%04x, 0x%04x): stub?\n", hWnd, hWndNext);
1189 if( hWndViewer )
1190 bRet = !SendMessage16( hWndViewer, WM_CHANGECBCHAIN,
1191 (WPARAM16)hWnd, (LPARAM)hWndNext);
1192 else
1193 WARN("hWndViewer is lost\n");
1195 if( hWnd == hWndViewer ) hWndViewer = hWndNext;
1197 return bRet;
1201 /**************************************************************************
1202 * IsClipboardFormatAvailable16 (USER.193)
1204 BOOL16 WINAPI IsClipboardFormatAvailable16( UINT16 wFormat )
1206 return IsClipboardFormatAvailable( wFormat );
1210 /**************************************************************************
1211 * IsClipboardFormatAvailable32 (USER32.340)
1213 BOOL WINAPI IsClipboardFormatAvailable( UINT wFormat )
1215 BOOL bRet;
1217 if (wFormat == 0) /* Reject this case quickly */
1218 bRet = FALSE;
1220 /* If WINE is not the clipboard selection owner ask the clipboard driver */
1221 else if ( !CLIPBOARD_Driver->pIsSelectionOwner() )
1222 bRet = CLIPBOARD_Driver->pIsFormatAvailable( (wFormat == CF_TEXT) ?
1223 CF_OEMTEXT : wFormat );
1224 /* Check if the format is in the local cache */
1225 else
1226 bRet = CLIPBOARD_IsPresent(wFormat);
1228 TRACE("(%04X)- ret(%d)\n", wFormat, bRet);
1229 return bRet;
1233 /**************************************************************************
1234 * GetOpenClipboardWindow16 (USER.248)
1235 * FIXME: This wont work if an external app owns the selection
1237 HWND16 WINAPI GetOpenClipboardWindow16(void)
1239 TRACE("()\n");
1240 return hWndClipWindow;
1244 /**************************************************************************
1245 * GetOpenClipboardWindow32 (USER32.277)
1246 * FIXME: This wont work if an external app owns the selection
1248 HWND WINAPI GetOpenClipboardWindow(void)
1250 TRACE("()\n");
1251 return hWndClipWindow;
1255 /**************************************************************************
1256 * GetPriorityClipboardFormat16 (USER.402)
1258 INT16 WINAPI GetPriorityClipboardFormat16( UINT16 *lpPriorityList, INT16 nCount)
1260 FIXME("(%p,%d): stub\n", lpPriorityList, nCount );
1261 return 0;
1265 /**************************************************************************
1266 * GetPriorityClipboardFormat32 (USER32.279)
1268 INT WINAPI GetPriorityClipboardFormat( UINT *lpPriorityList, INT nCount )
1270 int Counter;
1271 TRACE("()\n");
1273 if(CountClipboardFormats() == 0)
1275 return 0;
1278 for(Counter = 0; Counter <= nCount; Counter++)
1280 if(IsClipboardFormatAvailable(*(lpPriorityList+sizeof(INT)*Counter)))
1281 return *(lpPriorityList+sizeof(INT)*Counter);
1284 return -1;