Moved some macros like NULL, FALSE to winnt.h
[wine.git] / windows / clipboard.c
blob2da3a59e3b89a8c76a6771eb1ede290852dbebb5
1 /*
2 * WIN32 clipboard implementation
4 * Copyright 1994 Martin Ayotte
5 * 1996 Alex Korobka
6 * 1999 Noel Borthwick
8 * NOTES:
9 * This file contains the implementation for the WIN32 Clipboard API
10 * and Wine's internal clipboard cache.
11 * The actual contents of the clipboard are held in the clipboard cache.
12 * The internal implementation talks to a "clipboard driver" to fill or
13 * expose the cache to the native device. (Currently only the X11 and
14 * TTY clipboard driver are available)
16 * TODO:
20 #include <stdlib.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <fcntl.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include "windef.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29 #include "wine/winuser16.h"
30 #include "wine/winbase16.h"
31 #include "heap.h"
32 #include "message.h"
33 #include "task.h"
34 #include "queue.h"
35 #include "user.h"
36 #include "clipboard.h"
37 #include "debugtools.h"
39 DEFAULT_DEBUG_CHANNEL(clipboard);
41 #define CF_REGFORMATBASE 0xC000
43 /**************************************************************************
44 * Clipboard context global variables
47 static HANDLE hClipLock = 0;
48 static BOOL bCBHasChanged = FALSE;
50 HWND hWndClipWindow = 0; /* window that last opened clipboard */
51 HWND hWndClipOwner = 0; /* current clipboard owner */
52 HANDLE16 hTaskClipOwner = 0; /* clipboard owner's task */
53 static HWND hWndViewer = 0; /* start of viewers chain */
55 static WORD LastRegFormat = CF_REGFORMATBASE;
57 /* Clipboard cache initial data.
58 * WARNING: This data ordering is dependendent on the WINE_CLIPFORMAT structure
59 * declared in clipboard.h
61 WINE_CLIPFORMAT ClipFormats[] = {
62 { CF_TEXT, 1, 0, "Text", 0, 0, 0, 0, NULL, &ClipFormats[1]},
63 { CF_BITMAP, 1, 0, "Bitmap", 0, 0, 0, 0, &ClipFormats[0], &ClipFormats[2]},
64 { CF_METAFILEPICT, 1, 0, "MetaFile Picture", 0, 0, 0, 0, &ClipFormats[1], &ClipFormats[3]},
65 { CF_SYLK, 1, 0, "Sylk", 0, 0, 0, 0, &ClipFormats[2], &ClipFormats[4]},
66 { CF_DIF, 1, 0, "DIF", 0, 0, 0, 0, &ClipFormats[3], &ClipFormats[5]},
67 { CF_TIFF, 1, 0, "TIFF", 0, 0, 0, 0, &ClipFormats[4], &ClipFormats[6]},
68 { CF_OEMTEXT, 1, 0, "OEM Text", 0, 0, 0, 0, &ClipFormats[5], &ClipFormats[7]},
69 { CF_DIB, 1, 0, "DIB", 0, 0, 0, 0, &ClipFormats[6], &ClipFormats[8]},
70 { CF_PALETTE, 1, 0, "Palette", 0, 0, 0, 0, &ClipFormats[7], &ClipFormats[9]},
71 { CF_PENDATA, 1, 0, "PenData", 0, 0, 0, 0, &ClipFormats[8], &ClipFormats[10]},
72 { CF_RIFF, 1, 0, "RIFF", 0, 0, 0, 0, &ClipFormats[9], &ClipFormats[11]},
73 { CF_WAVE, 1, 0, "Wave", 0, 0, 0, 0, &ClipFormats[10], &ClipFormats[12]},
74 { CF_UNICODETEXT, 1, 0, "Unicode Text", 0, 0, 0, 0, &ClipFormats[11], &ClipFormats[13]},
75 { CF_OWNERDISPLAY, 1, 0, "Owner Display", 0, 0, 0, 0, &ClipFormats[12], &ClipFormats[14]},
76 { CF_DSPTEXT, 1, 0, "DSPText", 0, 0, 0, 0, &ClipFormats[13], &ClipFormats[15]},
77 { CF_DSPMETAFILEPICT, 1, 0, "DSPMetaFile Picture", 0, 0, 0, 0, &ClipFormats[14], &ClipFormats[16]},
78 { CF_DSPBITMAP, 1, 0, "DSPBitmap", 0, 0, 0, 0, &ClipFormats[15], &ClipFormats[17]},
79 { CF_HDROP, 1, 0, "HDROP", 0, 0, 0, 0, &ClipFormats[16], NULL}
83 /**************************************************************************
84 * Internal Clipboard implementation methods
85 **************************************************************************/
88 /**************************************************************************
89 * CLIPBOARD_LookupFormat
91 static LPWINE_CLIPFORMAT __lookup_format( LPWINE_CLIPFORMAT lpFormat, WORD wID )
93 while(TRUE)
95 if (lpFormat == NULL ||
96 lpFormat->wFormatID == wID) break;
97 lpFormat = lpFormat->NextFormat;
99 return lpFormat;
102 LPWINE_CLIPFORMAT CLIPBOARD_LookupFormat( WORD wID )
104 return __lookup_format( ClipFormats, wID );
107 /**************************************************************************
108 * CLIPBOARD_IsLocked
109 * Check if the clipboard cache is available to the caller
111 BOOL CLIPBOARD_IsLocked()
113 BOOL bIsLocked = TRUE;
114 HANDLE16 hTaskCur = GetCurrentTask();
117 * The clipboard is available:
118 * 1. if the caller's task has opened the clipboard,
119 * or
120 * 2. if the caller is the clipboard owners task, AND is responding to a
121 * WM_RENDERFORMAT message.
123 if ( hClipLock == hTaskCur )
124 bIsLocked = FALSE;
126 else if ( hTaskCur == hTaskClipOwner )
128 /* Check if we're currently executing inside a window procedure
129 * called in response to a WM_RENDERFORMAT message. A WM_RENDERFORMAT
130 * handler is not permitted to open the clipboard since it has been opened
131 * by another client. However the handler must have access to the
132 * clipboard in order to update data in response to this message.
134 MESSAGEQUEUE *queue = QUEUE_Lock( GetFastQueue16() );
136 if ( queue
137 && queue->smWaiting
138 && queue->smWaiting->msg == WM_RENDERFORMAT
139 && queue->smWaiting->hSrcQueue
141 bIsLocked = FALSE;
143 QUEUE_Unlock( queue );
146 return bIsLocked;
149 /**************************************************************************
150 * CLIPBOARD_ReleaseOwner
151 * Gives up ownership of the clipboard
153 void CLIPBOARD_ReleaseOwner()
155 hWndClipOwner = 0;
156 hTaskClipOwner = 0;
159 /**************************************************************************
160 * CLIPBOARD_GlobalFreeProc
162 * This is a callback mechanism to allow HGLOBAL data to be released in
163 * the context of the process which allocated it. We post a WM_TIMER message
164 * to the owner window(in CLIPBOARD_DeleteRecord) and destroy the data(in idEvent)
165 * in this WndProc, which is invoked when the apps message loop calls DispatchMessage.
166 * This technique is discussed in Matt Pietrek's "Under the Hood".
167 * An article describing the same may be found in MSDN by searching for WM_TIMER.
168 * Note that this mechanism will probably stop working when WINE supports
169 * address space separation. When "queue events" are implemented in Wine we
170 * should switch to using that mechanism, since it is more robust and does not
171 * require a procedure address to be passed. See the SetWinEventHook API for
172 * more info on this.
174 VOID CALLBACK CLIPBOARD_GlobalFreeProc( HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime )
176 /* idEvent is the HGLOBAL to be deleted */
177 GlobalFree( (HGLOBAL)idEvent );
180 /**************************************************************************
181 * CLIPBOARD_DeleteRecord
183 void CLIPBOARD_DeleteRecord(LPWINE_CLIPFORMAT lpFormat, BOOL bChange)
185 if( (lpFormat->wFormatID >= CF_GDIOBJFIRST &&
186 lpFormat->wFormatID <= CF_GDIOBJLAST) || lpFormat->wFormatID == CF_BITMAP
187 || lpFormat->wFormatID == CF_PALETTE)
189 if (lpFormat->hData32)
190 DeleteObject(lpFormat->hData32);
191 if (lpFormat->hData16)
192 DeleteObject(lpFormat->hData16);
194 else if( lpFormat->wFormatID == CF_METAFILEPICT )
196 if (lpFormat->hData32)
198 DeleteMetaFile( ((METAFILEPICT *)GlobalLock( lpFormat->hData32 ))->hMF );
199 PostMessageA(hWndClipOwner, WM_TIMER,
200 (WPARAM)lpFormat->hData32, (LPARAM)CLIPBOARD_GlobalFreeProc);
201 if (lpFormat->hDataSrc32)
203 /* Release lpFormat->hData32 in the context of the process which created it.
204 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
205 * GlobalFree(lpFormat->hDataSrc32);
207 PostMessageA(hWndClipOwner, WM_TIMER,
208 (WPARAM)lpFormat->hDataSrc32, (LPARAM)CLIPBOARD_GlobalFreeProc);
211 if (lpFormat->hData16)
212 /* HMETAFILE16 and HMETAFILE32 are apparently the same thing,
213 and a shallow copy is enough to share a METAFILEPICT
214 structure between 16bit and 32bit clipboards. The MetaFile
215 should of course only be deleted once. */
216 GlobalFree16(lpFormat->hData16);
218 if (lpFormat->hData16)
220 DeleteMetaFile16( ((METAFILEPICT16 *)GlobalLock16( lpFormat->hData16 ))->hMF );
221 GlobalFree16(lpFormat->hData16);
224 else
226 if (lpFormat->hData32)
228 /* Release lpFormat->hData32 in the context of the process which created it.
229 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
230 * GlobalFree( lpFormat->hData32 );
232 PostMessageA(hWndClipOwner, WM_TIMER,
233 (WPARAM)lpFormat->hData32, (LPARAM)CLIPBOARD_GlobalFreeProc);
235 if (lpFormat->hDataSrc32)
237 /* Release lpFormat->hData32 in the context of the process which created it.
238 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
239 * GlobalFree(lpFormat->hDataSrc32);
241 PostMessageA(hWndClipOwner, WM_TIMER,
242 (WPARAM)lpFormat->hDataSrc32, (LPARAM)CLIPBOARD_GlobalFreeProc);
244 if (lpFormat->hData16)
245 GlobalFree16(lpFormat->hData16);
248 lpFormat->wDataPresent = 0;
249 lpFormat->hData16 = 0;
250 lpFormat->hData32 = 0;
251 lpFormat->hDataSrc32 = 0;
252 lpFormat->drvData = 0;
254 if( bChange ) bCBHasChanged = TRUE;
257 /**************************************************************************
258 * CLIPBOARD_EmptyCache
260 void CLIPBOARD_EmptyCache( BOOL bChange )
262 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
264 while(lpFormat)
266 if ( lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32 )
267 CLIPBOARD_DeleteRecord( lpFormat, bChange );
269 lpFormat = lpFormat->NextFormat;
273 /**************************************************************************
274 * CLIPBOARD_IsPresent
276 BOOL CLIPBOARD_IsPresent(WORD wFormat)
278 /* special case */
280 if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT || wFormat == CF_UNICODETEXT )
281 return ClipFormats[CF_TEXT-1].wDataPresent ||
282 ClipFormats[CF_OEMTEXT-1].wDataPresent ||
283 ClipFormats[CF_UNICODETEXT-1].wDataPresent;
284 else
286 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
287 if( lpFormat ) return (lpFormat->wDataPresent);
289 return FALSE;
292 /**************************************************************************
293 * CLIPBOARD_IsCacheRendered
294 * Checks if any data needs to be rendered to the clipboard cache
295 * RETURNS:
296 * TRUE - All clipboard data is available in the cache
297 * FALSE - Some data is marked for delayed render and needs rendering
299 BOOL CLIPBOARD_IsCacheRendered()
301 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
303 /* check if all formats were rendered */
304 while(lpFormat)
306 if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
307 return FALSE;
309 lpFormat = lpFormat->NextFormat;
312 return TRUE;
316 /**************************************************************************
317 * CLIPBOARD_IsMemoryObject
318 * Tests if the clipboard format specifies a memory object
320 BOOL CLIPBOARD_IsMemoryObject( WORD wFormat )
322 switch(wFormat)
324 case CF_BITMAP:
325 case CF_METAFILEPICT:
326 case CF_DSPTEXT:
327 case CF_ENHMETAFILE:
328 case CF_HDROP:
329 case CF_PALETTE:
330 case CF_PENDATA:
331 return FALSE;
332 default:
333 return TRUE;
337 /***********************************************************************
338 * CLIPBOARD_GlobalDupMem( HGLOBAL )
339 * Helper method to duplicate an HGLOBAL chunk of memory into shared memory
341 HGLOBAL CLIPBOARD_GlobalDupMem( HGLOBAL hGlobalSrc )
343 HGLOBAL hGlobalDest;
344 PVOID pGlobalSrc, pGlobalDest;
345 DWORD cBytes;
347 if ( !hGlobalSrc )
348 return 0;
350 cBytes = GlobalSize(hGlobalSrc);
351 if ( 0 == cBytes )
352 return 0;
354 /* Turn on the DDESHARE and _MOVEABLE flags explicitly */
355 hGlobalDest = GlobalAlloc( GlobalFlags(hGlobalSrc) | GMEM_DDESHARE | GMEM_MOVEABLE,
356 cBytes );
357 if ( !hGlobalDest )
358 return 0;
360 pGlobalSrc = GlobalLock(hGlobalSrc);
361 pGlobalDest = GlobalLock(hGlobalDest);
362 if ( !pGlobalSrc || !pGlobalDest )
363 return 0;
365 memcpy(pGlobalDest, pGlobalSrc, cBytes);
367 GlobalUnlock(hGlobalSrc);
368 GlobalUnlock(hGlobalDest);
370 return hGlobalDest;
373 /**************************************************************************
374 * CLIPBOARD_GetFormatName
375 * Gets the format name associated with an ID
377 char * CLIPBOARD_GetFormatName(UINT wFormat)
379 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
380 return (lpFormat) ? lpFormat->Name : NULL;
384 /**************************************************************************
385 * CLIPBOARD_RenderFormat
387 static BOOL CLIPBOARD_RenderFormat(LPWINE_CLIPFORMAT lpFormat)
390 * If WINE is not the selection owner, and the format is available
391 * we must ask the the driver to render the data to the clipboard cache.
393 if ( !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 SendMessage16(hWndClipOwner,WM_RENDERFORMAT,
412 (WPARAM16)lpFormat->wFormatID,0L);
414 else
416 WARN("\thWndClipOwner (%04x) is lost!\n",
417 hWndClipOwner);
418 CLIPBOARD_ReleaseOwner();
419 lpFormat->wDataPresent = 0;
420 return FALSE;
424 return (lpFormat->hData16 || lpFormat->hData32) ? TRUE : FALSE;
427 /**************************************************************************
428 * CLIPBOARD_ConvertText
429 * Returns number of required/converted characters - not bytes!
431 static INT CLIPBOARD_ConvertText(WORD src_fmt, void const *src, INT src_size,
432 WORD dst_fmt, void *dst, INT dst_size)
434 UINT cp;
436 if(src_fmt == CF_UNICODETEXT)
438 switch(dst_fmt)
440 case CF_TEXT:
441 cp = CP_ACP;
442 break;
443 case CF_OEMTEXT:
444 cp = CP_OEMCP;
445 break;
446 default:
447 return 0;
449 return WideCharToMultiByte(cp, 0, src, src_size, dst, dst_size, NULL, NULL);
452 if(dst_fmt == CF_UNICODETEXT)
454 switch(src_fmt)
456 case CF_TEXT:
457 cp = CP_ACP;
458 break;
459 case CF_OEMTEXT:
460 cp = CP_OEMCP;
461 break;
462 default:
463 return 0;
465 return MultiByteToWideChar(cp, 0, src, src_size, dst, dst_size);
468 if(!dst_size) return src_size;
470 if(dst_size > src_size) dst_size = src_size;
472 if(src_fmt == CF_TEXT )
473 CharToOemBuffA(src, dst, dst_size);
474 else
475 OemToCharBuffA(src, dst, dst_size);
477 return dst_size;
480 /**************************************************************************
481 * CLIPBOARD_RenderText
483 * Renders text to the clipboard buffer converting between UNIX and DOS formats.
485 * RETURNS: pointer to the WINE_CLIPFORMAT if successful, NULL otherwise
487 * FIXME: Should be a pair of driver functions that convert between OEM text and Windows.
490 static LPWINE_CLIPFORMAT CLIPBOARD_RenderText( UINT wFormat )
492 LPWINE_CLIPFORMAT lpSource = ClipFormats;
493 LPWINE_CLIPFORMAT lpTarget;
495 /* Asked for CF_TEXT but not available - always attempt to convert
496 from CF_UNICODETEXT or CF_OEMTEXT */
497 if( wFormat == CF_TEXT && !ClipFormats[CF_TEXT-1].wDataPresent )
499 if(ClipFormats[CF_UNICODETEXT-1].wDataPresent)
501 /* Convert UNICODETEXT -> TEXT */
502 lpSource = &ClipFormats[CF_UNICODETEXT-1];
503 lpTarget = &ClipFormats[CF_TEXT-1];
505 TRACE("\tUNICODETEXT -> TEXT\n");
507 else if(ClipFormats[CF_OEMTEXT-1].wDataPresent)
509 /* Convert OEMTEXT -> TEXT */
510 lpSource = &ClipFormats[CF_OEMTEXT-1];
511 lpTarget = &ClipFormats[CF_TEXT-1];
513 TRACE("\tOEMTEXT -> TEXT\n");
515 else
516 lpSource = NULL; /* Conversion format is not available */
518 /* Asked for CF_OEMTEXT but not available - always attempt to convert
519 from CF_UNICODETEXT or CF_TEXT */
520 else if( wFormat == CF_OEMTEXT && !ClipFormats[CF_OEMTEXT-1].wDataPresent )
522 if(ClipFormats[CF_UNICODETEXT-1].wDataPresent)
524 /* Convert UNICODETEXT -> OEMTEXT */
525 lpSource = &ClipFormats[CF_UNICODETEXT-1];
526 lpTarget = &ClipFormats[CF_OEMTEXT-1];
528 TRACE("\tUNICODETEXT -> OEMTEXT\n");
530 else if(ClipFormats[CF_TEXT-1].wDataPresent)
532 /* Convert TEXT -> OEMTEXT */
533 lpSource = &ClipFormats[CF_TEXT-1];
534 lpTarget = &ClipFormats[CF_OEMTEXT-1];
536 TRACE("\tTEXT -> OEMTEXT\n");
538 else
539 lpSource = NULL; /* Conversion format is not available */
541 /* Asked for CF_UNICODETEXT but not available - always attempt to convert
542 from CF_TEXT or CF_OEMTEXT */
543 else if( wFormat == CF_UNICODETEXT && !ClipFormats[CF_UNICODETEXT-1].wDataPresent )
545 if(ClipFormats[CF_TEXT-1].wDataPresent)
547 /* Convert TEXT -> UNICODETEXT */
548 lpSource = &ClipFormats[CF_TEXT-1];
549 lpTarget = &ClipFormats[CF_UNICODETEXT-1];
551 TRACE("\tTEXT -> UNICODETEXT\n");
553 else if(ClipFormats[CF_OEMTEXT-1].wDataPresent)
555 /* Convert OEMTEXT -> UNICODETEXT */
556 lpSource = &ClipFormats[CF_OEMTEXT-1];
557 lpTarget = &ClipFormats[CF_UNICODETEXT-1];
559 TRACE("\tOEMTEXT -> UNICODETEXT\n");
561 else
562 lpSource = NULL; /* Conversion format is not available */
564 /* Text format requested is available - no conversion necessary */
565 else
567 lpSource = __lookup_format( ClipFormats, wFormat );
568 lpTarget = lpSource;
571 /* First render the source text format */
572 if ( !lpSource || !CLIPBOARD_RenderFormat(lpSource) ) return NULL;
574 /* Convert to the desired target text format, if necessary */
575 if( lpTarget != lpSource && !lpTarget->hData16 && !lpTarget->hData32 )
577 INT src_chars, dst_chars, alloc_size;
578 LPCSTR lpstrS;
579 LPSTR lpstrT;
581 if (lpSource->hData32)
583 lpstrS = (LPSTR)GlobalLock(lpSource->hData32);
585 else
587 lpstrS = (LPSTR)GlobalLock16(lpSource->hData16);
590 if( !lpstrS ) return NULL;
592 /* Text always NULL terminated */
593 if(lpSource->wFormatID == CF_UNICODETEXT)
594 src_chars = strlenW((LPCWSTR)lpstrS);
595 else
596 src_chars = strlen(lpstrS);
598 /* Calculate number of characters in the destination buffer */
599 dst_chars = CLIPBOARD_ConvertText(lpSource->wFormatID, lpstrS, src_chars,
600 lpTarget->wFormatID, NULL, 0);
601 if(!dst_chars) return NULL;
603 TRACE("\tconverting from '%s' to '%s', %i chars\n",
604 lpSource->Name, lpTarget->Name, src_chars);
606 /* Convert characters to bytes */
607 if(lpTarget->wFormatID == CF_UNICODETEXT)
608 alloc_size = dst_chars * sizeof(WCHAR);
609 else
610 alloc_size = dst_chars;
612 lpTarget->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, alloc_size);
613 lpstrT = (LPSTR)GlobalLock(lpTarget->hData32);
615 if( lpstrT )
617 CLIPBOARD_ConvertText(lpSource->wFormatID, lpstrS, src_chars,
618 lpTarget->wFormatID, lpstrT, dst_chars);
619 GlobalUnlock(lpTarget->hData32);
621 else
622 lpTarget->hData32 = 0;
624 /* Unlock source */
625 if (lpSource->hData32)
626 GlobalUnlock(lpSource->hData32);
627 else
628 GlobalUnlock16(lpSource->hData16);
631 return (lpTarget->hData16 || lpTarget->hData32) ? lpTarget : NULL;
634 /**************************************************************************
635 * WIN32 Clipboard implementation
636 **************************************************************************/
638 /**************************************************************************
639 * OpenClipboard16 (USER.137)
641 BOOL16 WINAPI OpenClipboard16( HWND16 hWnd )
643 return OpenClipboard( hWnd );
647 /**************************************************************************
648 * OpenClipboard (USER32.407)
650 * Note: Netscape uses NULL hWnd to open the clipboard.
652 BOOL WINAPI OpenClipboard( HWND hWnd )
654 BOOL bRet;
656 TRACE("(%04x)...\n", hWnd);
658 if (!hClipLock)
660 hClipLock = GetCurrentTask();
662 /* Save current user of the clipboard */
663 hWndClipWindow = hWnd;
664 bCBHasChanged = FALSE;
665 bRet = TRUE;
667 else bRet = FALSE;
669 TRACE(" returning %i\n", bRet);
670 return bRet;
674 /**************************************************************************
675 * CloseClipboard16 (USER.138)
677 BOOL16 WINAPI CloseClipboard16(void)
679 return CloseClipboard();
683 /**************************************************************************
684 * CloseClipboard (USER32.54)
686 BOOL WINAPI CloseClipboard(void)
688 TRACE("()\n");
690 if (hClipLock == GetCurrentTask())
692 hWndClipWindow = 0;
694 if (bCBHasChanged && hWndViewer)
695 SendMessage16(hWndViewer, WM_DRAWCLIPBOARD, 0, 0L);
696 hClipLock = 0;
698 return TRUE;
702 /**************************************************************************
703 * EmptyClipboard16 (USER.139)
705 BOOL16 WINAPI EmptyClipboard16(void)
707 return EmptyClipboard();
711 /**************************************************************************
712 * EmptyClipboard (USER32.169)
713 * Empties and acquires ownership of the clipboard
715 BOOL WINAPI EmptyClipboard(void)
717 TRACE("()\n");
719 if (hClipLock != GetCurrentTask())
721 WARN("Clipboard not opened by calling task!");
722 return FALSE;
725 /* destroy private objects */
727 if (hWndClipOwner)
728 SendMessage16(hWndClipOwner, WM_DESTROYCLIPBOARD, 0, 0L);
730 /* empty the cache */
731 CLIPBOARD_EmptyCache(TRUE);
733 /* Assign ownership of the clipboard to the current client */
734 hWndClipOwner = hWndClipWindow;
736 /* Save the current task */
737 hTaskClipOwner = GetCurrentTask();
739 /* Tell the driver to acquire the selection */
740 USER_Driver.pAcquireClipboard();
742 return TRUE;
746 /**************************************************************************
747 * GetClipboardOwner16 (USER.140)
748 * FIXME: Can't return the owner if the clipbard is owned by an external app
750 HWND16 WINAPI GetClipboardOwner16(void)
752 TRACE("()\n");
753 return hWndClipOwner;
757 /**************************************************************************
758 * GetClipboardOwner (USER32.225)
759 * FIXME: Can't return the owner if the clipbard is owned by an external app
761 HWND WINAPI GetClipboardOwner(void)
763 TRACE("()\n");
764 return hWndClipOwner;
768 /**************************************************************************
769 * SetClipboardData16 (USER.141)
771 HANDLE16 WINAPI SetClipboardData16( UINT16 wFormat, HANDLE16 hData )
773 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
775 TRACE("(%04X, %04x) !\n", wFormat, hData);
777 /* NOTE: If the hData is zero and current owner doesn't match
778 * the window that opened the clipboard then this application
779 * is screwed because WM_RENDERFORMAT will go to the owner.
780 * (to become the owner it must call EmptyClipboard() before
781 * adding new data).
784 if( CLIPBOARD_IsLocked() || !lpFormat ||
785 (!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) )
787 WARN("Invalid hData or clipboard not opened by calling task!\n");
788 return 0;
791 /* Pass on the request to the driver */
792 USER_Driver.pSetClipboardData(wFormat);
794 if ( lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32 )
796 CLIPBOARD_DeleteRecord(lpFormat, TRUE);
798 /* delete existing CF_UNICODETEXT/CF_TEXT/CF_OEMTEXT aliases */
799 if(wFormat == CF_UNICODETEXT)
801 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
802 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
804 else if(wFormat == CF_TEXT)
806 CLIPBOARD_DeleteRecord(&ClipFormats[CF_UNICODETEXT-1], TRUE);
807 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
809 else if(wFormat == CF_OEMTEXT)
811 CLIPBOARD_DeleteRecord(&ClipFormats[CF_UNICODETEXT-1], TRUE);
812 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
816 bCBHasChanged = TRUE;
817 lpFormat->wDataPresent = 1;
818 lpFormat->hData16 = hData; /* 0 is legal, see WM_RENDERFORMAT */
819 lpFormat->hData32 = 0;
821 return lpFormat->hData16;
825 /**************************************************************************
826 * SetClipboardData (USER32.470)
828 HANDLE WINAPI SetClipboardData( UINT wFormat, HANDLE hData )
830 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
832 TRACE("(%08X, %08x) !\n", wFormat, hData);
834 /* NOTE: If the hData is zero and current owner doesn't match
835 * the window that opened the clipboard then this application
836 * is screwed because WM_RENDERFORMAT will go to the owner.
837 * (to become the owner it must call EmptyClipboard() before
838 * adding new data).
841 if( CLIPBOARD_IsLocked() || !lpFormat ||
842 (!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) )
844 WARN("Invalid hData or clipboard not opened by calling task!\n");
845 return 0;
848 /* Tell the driver to acquire the selection */
849 USER_Driver.pAcquireClipboard();
851 if ( lpFormat->wDataPresent &&
852 (lpFormat->hData16 || lpFormat->hData32) )
854 CLIPBOARD_DeleteRecord(lpFormat, TRUE);
856 /* delete existing CF_UNICODETEXT/CF_TEXT/CF_OEMTEXT aliases */
857 if(wFormat == CF_UNICODETEXT)
859 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
860 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
862 else if(wFormat == CF_TEXT)
864 CLIPBOARD_DeleteRecord(&ClipFormats[CF_UNICODETEXT-1], TRUE);
865 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
867 else if(wFormat == CF_OEMTEXT)
869 CLIPBOARD_DeleteRecord(&ClipFormats[CF_UNICODETEXT-1], TRUE);
870 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
874 bCBHasChanged = TRUE;
875 lpFormat->wDataPresent = 1;
876 lpFormat->hDataSrc32 = hData; /* Save the source handle */
879 * Make a shared duplicate if the memory is not shared
880 * TODO: What should be done for non-memory objects
882 if ( CLIPBOARD_IsMemoryObject(wFormat) && hData && !(GlobalFlags(hData) & GMEM_DDESHARE) )
883 lpFormat->hData32 = CLIPBOARD_GlobalDupMem( hData );
884 else
885 lpFormat->hData32 = hData; /* 0 is legal, see WM_RENDERFORMAT */
887 lpFormat->hData16 = 0;
889 return lpFormat->hData32; /* Should we return lpFormat->hDataSrc32 */
893 /**************************************************************************
894 * GetClipboardData16 (USER.142)
896 HANDLE16 WINAPI GetClipboardData16( UINT16 wFormat )
898 LPWINE_CLIPFORMAT lpRender = ClipFormats;
900 TRACE("(%04X)\n", wFormat);
902 if (CLIPBOARD_IsLocked())
904 WARN("Clipboard not opened by calling task!\n");
905 return 0;
908 if( wFormat == CF_UNICODETEXT || wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
910 lpRender = CLIPBOARD_RenderText(wFormat);
911 if ( !lpRender ) return 0;
913 else
915 lpRender = __lookup_format( ClipFormats, wFormat );
916 if( !lpRender || !CLIPBOARD_RenderFormat(lpRender) ) return 0;
919 /* Convert between 32 -> 16 bit data, if necessary */
920 if( lpRender->hData32 && !lpRender->hData16
921 && CLIPBOARD_IsMemoryObject(wFormat) )
923 int size;
924 if( lpRender->wFormatID == CF_METAFILEPICT )
925 size = sizeof( METAFILEPICT16 );
926 else
927 size = GlobalSize(lpRender->hData32);
929 lpRender->hData16 = GlobalAlloc16(GMEM_ZEROINIT, size);
930 if( !lpRender->hData16 )
931 ERR("(%04X) -- not enough memory in 16b heap\n", wFormat);
932 else
934 if( lpRender->wFormatID == CF_METAFILEPICT )
936 FIXME("\timplement function CopyMetaFilePict32to16\n");
937 FIXME("\tin the appropriate file.\n");
938 #ifdef SOMEONE_IMPLEMENTED_ME
939 CopyMetaFilePict32to16( GlobalLock16(lpRender->hData16),
940 GlobalLock(lpRender->hData32) );
941 #endif
943 else
945 memcpy( GlobalLock16(lpRender->hData16),
946 GlobalLock(lpRender->hData32),
947 size );
949 GlobalUnlock16(lpRender->hData16);
950 GlobalUnlock(lpRender->hData32);
954 TRACE("\treturning %04x (type %i)\n",
955 lpRender->hData16, lpRender->wFormatID);
956 return lpRender->hData16;
960 /**************************************************************************
961 * GetClipboardData (USER32.222)
963 HANDLE WINAPI GetClipboardData( UINT wFormat )
965 LPWINE_CLIPFORMAT lpRender = ClipFormats;
967 TRACE("(%08X)\n", wFormat);
969 if (CLIPBOARD_IsLocked())
971 WARN("Clipboard not opened by calling task!");
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 16 -> 32 bit data, if necessary */
987 if( lpRender->hData16 && !lpRender->hData32
988 && CLIPBOARD_IsMemoryObject(wFormat) )
990 int size;
991 if( lpRender->wFormatID == CF_METAFILEPICT )
992 size = sizeof( METAFILEPICT );
993 else
994 size = GlobalSize16(lpRender->hData16);
995 lpRender->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE,
996 size);
997 if( lpRender->wFormatID == CF_METAFILEPICT )
999 FIXME("\timplement function CopyMetaFilePict16to32\n");
1000 FIXME("\tin the appropriate file.\n");
1001 #ifdef SOMEONE_IMPLEMENTED_ME
1002 CopyMetaFilePict16to32( GlobalLock16(lpRender->hData32),
1003 GlobalLock(lpRender->hData16) );
1004 #endif
1006 else
1008 memcpy( GlobalLock(lpRender->hData32),
1009 GlobalLock16(lpRender->hData16),
1010 size );
1012 GlobalUnlock(lpRender->hData32);
1013 GlobalUnlock16(lpRender->hData16);
1016 TRACE("\treturning %04x (type %i)\n",
1017 lpRender->hData32, lpRender->wFormatID);
1018 return lpRender->hData32;
1022 /**************************************************************************
1023 * CountClipboardFormats16 (USER.143)
1025 INT16 WINAPI CountClipboardFormats16(void)
1027 return CountClipboardFormats();
1031 /**************************************************************************
1032 * CountClipboardFormats (USER32.63)
1034 INT WINAPI CountClipboardFormats(void)
1036 INT FormatCount = 0;
1037 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
1039 TRACE("()\n");
1041 while(TRUE)
1043 if (lpFormat == NULL) break;
1045 if( lpFormat->wFormatID != CF_TEXT ) /* Don't count CF_TEXT */
1048 * The format is available if either:
1049 * 1. The data is already in the cache.
1050 * 2. The selection is not owned by us(WINE) and the data is
1051 * available to the clipboard driver.
1053 if ( lpFormat->wDataPresent ||
1054 ( !USER_Driver.pIsSelectionOwner()
1055 && USER_Driver.pIsClipboardFormatAvailable( lpFormat->wFormatID ) ) )
1057 TRACE("\tdata found for format 0x%04x(%s)\n",
1058 lpFormat->wFormatID, CLIPBOARD_GetFormatName(lpFormat->wFormatID));
1059 FormatCount++;
1063 lpFormat = lpFormat->NextFormat;
1066 /* these are equivalent, adjust the total */
1067 FormatCount += (ClipFormats[CF_UNICODETEXT-1].wDataPresent ||
1068 ClipFormats[CF_TEXT-1].wDataPresent ||
1069 ClipFormats[CF_OEMTEXT-1].wDataPresent) ? 1 : 0;
1071 TRACE("\ttotal %d\n", FormatCount);
1072 return FormatCount;
1076 /**************************************************************************
1077 * EnumClipboardFormats16 (USER.144)
1079 UINT16 WINAPI EnumClipboardFormats16( UINT16 wFormat )
1081 return EnumClipboardFormats( wFormat );
1085 /**************************************************************************
1086 * EnumClipboardFormats (USER32.179)
1088 UINT WINAPI EnumClipboardFormats( UINT wFormat )
1090 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
1091 BOOL bFormatPresent;
1093 TRACE("(%04X)\n", wFormat);
1095 if (CLIPBOARD_IsLocked())
1097 WARN("Clipboard not opened by calling task!");
1098 return 0;
1101 if (wFormat == 0) /* start from the beginning */
1102 lpFormat = ClipFormats;
1103 else
1105 /* walk up to the specified format record */
1107 if( !(lpFormat = __lookup_format( lpFormat, wFormat )) )
1108 return 0;
1109 lpFormat = lpFormat->NextFormat; /* right */
1112 while(TRUE)
1114 if (lpFormat == NULL) return 0;
1116 if(CLIPBOARD_IsPresent(lpFormat->wFormatID))
1117 break;
1119 /* Query the driver if not yet in the cache */
1120 if (!USER_Driver.pIsSelectionOwner())
1122 if(lpFormat->wFormatID == CF_UNICODETEXT ||
1123 lpFormat->wFormatID == CF_TEXT ||
1124 lpFormat->wFormatID == CF_OEMTEXT)
1126 if(USER_Driver.pIsClipboardFormatAvailable(CF_UNICODETEXT) ||
1127 USER_Driver.pIsClipboardFormatAvailable(CF_TEXT) ||
1128 USER_Driver.pIsClipboardFormatAvailable(CF_OEMTEXT))
1129 bFormatPresent = TRUE;
1130 else
1131 bFormatPresent = FALSE;
1133 else
1134 bFormatPresent = USER_Driver.pIsClipboardFormatAvailable(lpFormat->wFormatID);
1136 if(bFormatPresent)
1137 break;
1140 lpFormat = lpFormat->NextFormat;
1143 TRACE("Next available format %d\n", lpFormat->wFormatID);
1145 return lpFormat->wFormatID;
1149 /**************************************************************************
1150 * RegisterClipboardFormat16 (USER.145)
1152 UINT16 WINAPI RegisterClipboardFormat16( LPCSTR FormatName )
1154 LPWINE_CLIPFORMAT lpNewFormat;
1155 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
1157 if (FormatName == NULL) return 0;
1159 TRACE("('%s') !\n", FormatName);
1161 /* walk format chain to see if it's already registered */
1163 while(TRUE)
1165 if ( !strcmp(lpFormat->Name,FormatName) )
1167 lpFormat->wRefCount++;
1168 return lpFormat->wFormatID;
1171 if ( lpFormat->NextFormat == NULL ) break;
1173 lpFormat = lpFormat->NextFormat;
1176 /* allocate storage for new format entry */
1178 lpNewFormat = (LPWINE_CLIPFORMAT)HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_CLIPFORMAT));
1179 if(lpNewFormat == NULL) {
1180 WARN("No more memory for a new format!");
1181 return 0;
1183 lpFormat->NextFormat = lpNewFormat;
1184 lpNewFormat->wFormatID = LastRegFormat;
1185 lpNewFormat->wRefCount = 1;
1187 lpNewFormat->Name = (LPSTR)HEAP_strdupA(GetProcessHeap(), 0, FormatName);
1188 if(lpNewFormat->Name == NULL) {
1189 WARN("No more memory for the new format name!");
1190 HeapFree(GetProcessHeap(), 0, lpNewFormat);
1191 return 0;
1194 lpNewFormat->wDataPresent = 0;
1195 lpNewFormat->hData16 = 0;
1196 lpNewFormat->hDataSrc32 = 0;
1197 lpNewFormat->hData32 = 0;
1198 lpNewFormat->drvData = 0;
1199 lpNewFormat->PrevFormat = lpFormat;
1200 lpNewFormat->NextFormat = NULL;
1202 /* Pass on the registration request to the driver */
1203 USER_Driver.pRegisterClipboardFormat( FormatName );
1205 return LastRegFormat++;
1209 /**************************************************************************
1210 * RegisterClipboardFormatA (USER32.431)
1212 UINT WINAPI RegisterClipboardFormatA( LPCSTR formatName )
1214 return RegisterClipboardFormat16( formatName );
1218 /**************************************************************************
1219 * RegisterClipboardFormatW (USER32.432)
1221 UINT WINAPI RegisterClipboardFormatW( LPCWSTR formatName )
1223 LPSTR aFormat = HEAP_strdupWtoA( GetProcessHeap(), 0, formatName );
1224 UINT ret = RegisterClipboardFormatA( aFormat );
1225 HeapFree( GetProcessHeap(), 0, aFormat );
1226 return ret;
1230 /**************************************************************************
1231 * GetClipboardFormatName16 (USER.146)
1233 INT16 WINAPI GetClipboardFormatName16( UINT16 wFormat, LPSTR retStr, INT16 maxlen )
1235 return GetClipboardFormatNameA( wFormat, retStr, maxlen );
1239 /**************************************************************************
1240 * GetClipboardFormatNameA (USER32.223)
1242 INT WINAPI GetClipboardFormatNameA( UINT wFormat, LPSTR retStr, INT maxlen )
1244 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
1246 TRACE("(%04X, %p, %d) !\n", wFormat, retStr, maxlen);
1248 if (lpFormat == NULL || lpFormat->Name == NULL ||
1249 lpFormat->wFormatID < CF_REGFORMATBASE) return 0;
1251 TRACE("Name='%s' !\n", lpFormat->Name);
1253 lstrcpynA( retStr, lpFormat->Name, maxlen );
1254 return strlen(retStr);
1258 /**************************************************************************
1259 * GetClipboardFormatNameW (USER32.224)
1261 INT WINAPI GetClipboardFormatNameW( UINT wFormat, LPWSTR retStr, INT maxlen )
1263 INT ret;
1264 LPSTR p = HeapAlloc( GetProcessHeap(), 0, maxlen );
1265 if(p == NULL) return 0; /* FIXME: is this the correct failure value? */
1267 ret = GetClipboardFormatNameA( wFormat, p, maxlen );
1269 if (maxlen > 0 && !MultiByteToWideChar( CP_ACP, 0, p, -1, retStr, maxlen ))
1270 retStr[maxlen-1] = 0;
1271 HeapFree( GetProcessHeap(), 0, p );
1272 return ret;
1276 /**************************************************************************
1277 * SetClipboardViewer16 (USER.147)
1279 HWND16 WINAPI SetClipboardViewer16( HWND16 hWnd )
1281 TRACE("(%04x)\n", hWnd);
1282 return SetClipboardViewer( hWnd );
1286 /**************************************************************************
1287 * SetClipboardViewer (USER32.471)
1289 HWND WINAPI SetClipboardViewer( HWND hWnd )
1291 HWND hwndPrev = hWndViewer;
1293 TRACE("(%04x): returning %04x\n", hWnd, hwndPrev);
1295 hWndViewer = hWnd;
1296 return hwndPrev;
1300 /**************************************************************************
1301 * GetClipboardViewer16 (USER.148)
1303 HWND16 WINAPI GetClipboardViewer16(void)
1305 TRACE("()\n");
1306 return hWndViewer;
1310 /**************************************************************************
1311 * GetClipboardViewer (USER32.226)
1313 HWND WINAPI GetClipboardViewer(void)
1315 TRACE("()\n");
1316 return hWndViewer;
1320 /**************************************************************************
1321 * ChangeClipboardChain16 (USER.149)
1323 BOOL16 WINAPI ChangeClipboardChain16(HWND16 hWnd, HWND16 hWndNext)
1325 return ChangeClipboardChain(hWnd, hWndNext);
1329 /**************************************************************************
1330 * ChangeClipboardChain (USER32.22)
1332 BOOL WINAPI ChangeClipboardChain(HWND hWnd, HWND hWndNext)
1334 BOOL bRet = 0;
1336 FIXME("(0x%04x, 0x%04x): stub?\n", hWnd, hWndNext);
1338 if( hWndViewer )
1339 bRet = !SendMessage16( hWndViewer, WM_CHANGECBCHAIN,
1340 (WPARAM16)hWnd, (LPARAM)hWndNext);
1341 else
1342 WARN("hWndViewer is lost\n");
1344 if( hWnd == hWndViewer ) hWndViewer = hWndNext;
1346 return bRet;
1350 /**************************************************************************
1351 * IsClipboardFormatAvailable16 (USER.193)
1353 BOOL16 WINAPI IsClipboardFormatAvailable16( UINT16 wFormat )
1355 return IsClipboardFormatAvailable( wFormat );
1359 /**************************************************************************
1360 * IsClipboardFormatAvailable (USER32.340)
1362 BOOL WINAPI IsClipboardFormatAvailable( UINT wFormat )
1364 BOOL bRet;
1366 if (wFormat == 0) /* Reject this case quickly */
1367 bRet = FALSE;
1368 else
1369 bRet = EnumClipboardFormats(wFormat - 1) == wFormat;
1371 TRACE("(%04X)- ret(%d)\n", wFormat, bRet);
1372 return bRet;
1376 /**************************************************************************
1377 * GetOpenClipboardWindow16 (USER.248)
1378 * FIXME: This wont work if an external app owns the selection
1380 HWND16 WINAPI GetOpenClipboardWindow16(void)
1382 TRACE("()\n");
1383 return hWndClipWindow;
1387 /**************************************************************************
1388 * GetOpenClipboardWindow (USER32.277)
1389 * FIXME: This wont work if an external app owns the selection
1391 HWND WINAPI GetOpenClipboardWindow(void)
1393 TRACE("()\n");
1394 return hWndClipWindow;
1398 /**************************************************************************
1399 * GetPriorityClipboardFormat16 (USER.402)
1401 INT16 WINAPI GetPriorityClipboardFormat16( UINT16 *lpPriorityList, INT16 nCount)
1403 FIXME("(%p,%d): stub\n", lpPriorityList, nCount );
1404 return 0;
1408 /**************************************************************************
1409 * GetPriorityClipboardFormat (USER32.279)
1411 INT WINAPI GetPriorityClipboardFormat( UINT *lpPriorityList, INT nCount )
1413 int Counter;
1414 TRACE("()\n");
1416 if(CountClipboardFormats() == 0)
1418 return 0;
1421 for(Counter = 0; Counter <= nCount; Counter++)
1423 if(IsClipboardFormatAvailable(*(lpPriorityList+sizeof(INT)*Counter)))
1424 return *(lpPriorityList+sizeof(INT)*Counter);
1427 return -1;
1431 /**************************************************************************
1432 * GetClipboardSequenceNumber (USER32)
1433 * Supported on Win2k/Win98
1434 * MSDN: Windows clipboard code keeps a serial number for the clipboard
1435 * for each window station. The number is incremented whenever the
1436 * contents change or are emptied.
1437 * If you do not have WINSTA_ACCESSCLIPBOARD then the function returns 0
1439 DWORD WINAPI GetClipboardSequenceNumber(VOID)
1441 FIXME("Returning 0, see windows/clipboard.c\n");
1442 /* FIXME: Use serial numbers */
1443 return 0;