Added LOAD_WITH_ALTERED_SEARCH_PATH support to LoadLibraryEx.
[wine/dcerpc.git] / windows / clipboard.c
blob9a2d1e36d51ba159d7c3378ad878a701bb2b4bd1
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 <fcntl.h>
23 #include <unistd.h>
24 #include <string.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "wingdi.h"
29 #include "winuser.h"
30 #include "wine/winuser16.h"
31 #include "wine/winbase16.h"
32 #include "heap.h"
33 #include "user.h"
34 #include "clipboard.h"
35 #include "debugtools.h"
37 DEFAULT_DEBUG_CHANNEL(clipboard);
39 #define CF_REGFORMATBASE 0xC000
41 /**************************************************************************
42 * Clipboard context global variables
45 static HANDLE hClipLock = 0;
46 static BOOL bCBHasChanged = FALSE;
48 HWND hWndClipWindow = 0; /* window that last opened clipboard */
49 HWND hWndClipOwner = 0; /* current clipboard owner */
50 HANDLE16 hTaskClipOwner = 0; /* clipboard owner's task */
51 static HWND hWndViewer = 0; /* start of viewers chain */
53 static WORD LastRegFormat = CF_REGFORMATBASE;
55 /* Clipboard cache initial data.
56 * WARNING: This data ordering is dependent on the WINE_CLIPFORMAT structure
57 * declared in clipboard.h
59 WINE_CLIPFORMAT ClipFormats[] = {
60 { CF_TEXT, 1, 0, "Text", 0, 0, 0, 0, NULL, &ClipFormats[1]},
61 { CF_BITMAP, 1, 0, "Bitmap", 0, 0, 0, 0, &ClipFormats[0], &ClipFormats[2]},
62 { CF_METAFILEPICT, 1, 0, "MetaFile Picture", 0, 0, 0, 0, &ClipFormats[1], &ClipFormats[3]},
63 { CF_SYLK, 1, 0, "Sylk", 0, 0, 0, 0, &ClipFormats[2], &ClipFormats[4]},
64 { CF_DIF, 1, 0, "DIF", 0, 0, 0, 0, &ClipFormats[3], &ClipFormats[5]},
65 { CF_TIFF, 1, 0, "TIFF", 0, 0, 0, 0, &ClipFormats[4], &ClipFormats[6]},
66 { CF_OEMTEXT, 1, 0, "OEM Text", 0, 0, 0, 0, &ClipFormats[5], &ClipFormats[7]},
67 { CF_DIB, 1, 0, "DIB", 0, 0, 0, 0, &ClipFormats[6], &ClipFormats[8]},
68 { CF_PALETTE, 1, 0, "Palette", 0, 0, 0, 0, &ClipFormats[7], &ClipFormats[9]},
69 { CF_PENDATA, 1, 0, "PenData", 0, 0, 0, 0, &ClipFormats[8], &ClipFormats[10]},
70 { CF_RIFF, 1, 0, "RIFF", 0, 0, 0, 0, &ClipFormats[9], &ClipFormats[11]},
71 { CF_WAVE, 1, 0, "Wave", 0, 0, 0, 0, &ClipFormats[10], &ClipFormats[12]},
72 { CF_UNICODETEXT, 1, 0, "Unicode Text", 0, 0, 0, 0, &ClipFormats[11], &ClipFormats[13]},
73 { CF_OWNERDISPLAY, 1, 0, "Owner Display", 0, 0, 0, 0, &ClipFormats[12], &ClipFormats[14]},
74 { CF_DSPTEXT, 1, 0, "DSPText", 0, 0, 0, 0, &ClipFormats[13], &ClipFormats[15]},
75 { CF_DSPMETAFILEPICT, 1, 0, "DSPMetaFile Picture", 0, 0, 0, 0, &ClipFormats[14], &ClipFormats[16]},
76 { CF_DSPBITMAP, 1, 0, "DSPBitmap", 0, 0, 0, 0, &ClipFormats[15], &ClipFormats[17]},
77 { CF_HDROP, 1, 0, "HDROP", 0, 0, 0, 0, &ClipFormats[16], 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 #if 0
133 MESSAGEQUEUE *queue = QUEUE_Current();
135 if ( queue
136 && queue->smWaiting
137 && queue->smWaiting->msg == WM_RENDERFORMAT
138 && queue->smWaiting->hSrcQueue
140 bIsLocked = FALSE;
141 #else
142 /* FIXME: queue check no longer possible */
143 bIsLocked = FALSE;
144 #endif
147 return bIsLocked;
150 /**************************************************************************
151 * CLIPBOARD_ReleaseOwner
152 * Gives up ownership of the clipboard
154 void CLIPBOARD_ReleaseOwner()
156 hWndClipOwner = 0;
157 hTaskClipOwner = 0;
160 /**************************************************************************
161 * CLIPBOARD_GlobalFreeProc
163 * This is a callback mechanism to allow HGLOBAL data to be released in
164 * the context of the process which allocated it. We post a WM_TIMER message
165 * to the owner window(in CLIPBOARD_DeleteRecord) and destroy the data(in idEvent)
166 * in this WndProc, which is invoked when the apps message loop calls DispatchMessage.
167 * This technique is discussed in Matt Pietrek's "Under the Hood".
168 * An article describing the same may be found in MSDN by searching for WM_TIMER.
169 * Note that this mechanism will probably stop working when WINE supports
170 * address space separation. When "queue events" are implemented in Wine we
171 * should switch to using that mechanism, since it is more robust and does not
172 * require a procedure address to be passed. See the SetWinEventHook API for
173 * more info on this.
175 VOID CALLBACK CLIPBOARD_GlobalFreeProc( HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime )
177 /* idEvent is the HGLOBAL to be deleted */
178 GlobalFree( (HGLOBAL)idEvent );
181 /**************************************************************************
182 * CLIPBOARD_DeleteRecord
184 void CLIPBOARD_DeleteRecord(LPWINE_CLIPFORMAT lpFormat, BOOL bChange)
186 if( (lpFormat->wFormatID >= CF_GDIOBJFIRST &&
187 lpFormat->wFormatID <= CF_GDIOBJLAST) || lpFormat->wFormatID == CF_BITMAP
188 || lpFormat->wFormatID == CF_PALETTE)
190 if (lpFormat->hData32)
191 DeleteObject(lpFormat->hData32);
192 if (lpFormat->hData16)
193 DeleteObject(lpFormat->hData16);
195 else if( lpFormat->wFormatID == CF_METAFILEPICT )
197 if (lpFormat->hData32)
199 DeleteMetaFile( ((METAFILEPICT *)GlobalLock( lpFormat->hData32 ))->hMF );
200 PostMessageA(hWndClipOwner, WM_TIMER,
201 (WPARAM)lpFormat->hData32, (LPARAM)CLIPBOARD_GlobalFreeProc);
202 if (lpFormat->hDataSrc32)
204 /* Release lpFormat->hData32 in the context of the process which created it.
205 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
206 * GlobalFree(lpFormat->hDataSrc32);
208 PostMessageA(hWndClipOwner, WM_TIMER,
209 (WPARAM)lpFormat->hDataSrc32, (LPARAM)CLIPBOARD_GlobalFreeProc);
212 if (lpFormat->hData16)
213 /* HMETAFILE16 and HMETAFILE32 are apparently the same thing,
214 and a shallow copy is enough to share a METAFILEPICT
215 structure between 16bit and 32bit clipboards. The MetaFile
216 should of course only be deleted once. */
217 GlobalFree16(lpFormat->hData16);
219 if (lpFormat->hData16)
221 DeleteMetaFile16( ((METAFILEPICT16 *)GlobalLock16( lpFormat->hData16 ))->hMF );
222 GlobalFree16(lpFormat->hData16);
225 else
227 if (lpFormat->hData32)
229 /* Release lpFormat->hData32 in the context of the process which created it.
230 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
231 * GlobalFree( lpFormat->hData32 );
233 PostMessageA(hWndClipOwner, WM_TIMER,
234 (WPARAM)lpFormat->hData32, (LPARAM)CLIPBOARD_GlobalFreeProc);
236 if (lpFormat->hDataSrc32)
238 /* Release lpFormat->hData32 in the context of the process which created it.
239 * See CLIPBOARD_GlobalFreeProc for more details about this technique.
240 * GlobalFree(lpFormat->hDataSrc32);
242 PostMessageA(hWndClipOwner, WM_TIMER,
243 (WPARAM)lpFormat->hDataSrc32, (LPARAM)CLIPBOARD_GlobalFreeProc);
245 if (lpFormat->hData16)
246 GlobalFree16(lpFormat->hData16);
249 lpFormat->wDataPresent = 0;
250 lpFormat->hData16 = 0;
251 lpFormat->hData32 = 0;
252 lpFormat->hDataSrc32 = 0;
253 lpFormat->drvData = 0;
255 if( bChange ) bCBHasChanged = TRUE;
258 /**************************************************************************
259 * CLIPBOARD_EmptyCache
261 void CLIPBOARD_EmptyCache( BOOL bChange )
263 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
265 while(lpFormat)
267 if ( lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32 )
268 CLIPBOARD_DeleteRecord( lpFormat, bChange );
270 lpFormat = lpFormat->NextFormat;
274 /**************************************************************************
275 * CLIPBOARD_IsPresent
277 BOOL CLIPBOARD_IsPresent(WORD wFormat)
279 /* special case */
281 if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT || wFormat == CF_UNICODETEXT )
282 return ClipFormats[CF_TEXT-1].wDataPresent ||
283 ClipFormats[CF_OEMTEXT-1].wDataPresent ||
284 ClipFormats[CF_UNICODETEXT-1].wDataPresent;
285 else
287 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
288 if( lpFormat ) return (lpFormat->wDataPresent);
290 return FALSE;
293 /**************************************************************************
294 * CLIPBOARD_IsCacheRendered
295 * Checks if any data needs to be rendered to the clipboard cache
296 * RETURNS:
297 * TRUE - All clipboard data is available in the cache
298 * FALSE - Some data is marked for delayed render and needs rendering
300 BOOL CLIPBOARD_IsCacheRendered()
302 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
304 /* check if all formats were rendered */
305 while(lpFormat)
307 if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
308 return FALSE;
310 lpFormat = lpFormat->NextFormat;
313 return TRUE;
317 /**************************************************************************
318 * CLIPBOARD_IsMemoryObject
319 * Tests if the clipboard format specifies a memory object
321 BOOL CLIPBOARD_IsMemoryObject( WORD wFormat )
323 switch(wFormat)
325 case CF_BITMAP:
326 case CF_METAFILEPICT:
327 case CF_DSPTEXT:
328 case CF_ENHMETAFILE:
329 case CF_HDROP:
330 case CF_PALETTE:
331 case CF_PENDATA:
332 return FALSE;
333 default:
334 return TRUE;
338 /***********************************************************************
339 * CLIPBOARD_GlobalDupMem( HGLOBAL )
340 * Helper method to duplicate an HGLOBAL chunk of memory into shared memory
342 HGLOBAL CLIPBOARD_GlobalDupMem( HGLOBAL hGlobalSrc )
344 HGLOBAL hGlobalDest;
345 PVOID pGlobalSrc, pGlobalDest;
346 DWORD cBytes;
348 if ( !hGlobalSrc )
349 return 0;
351 cBytes = GlobalSize(hGlobalSrc);
352 if ( 0 == cBytes )
353 return 0;
355 /* Turn on the DDESHARE and _MOVEABLE flags explicitly */
356 hGlobalDest = GlobalAlloc( GlobalFlags(hGlobalSrc) | GMEM_DDESHARE | GMEM_MOVEABLE,
357 cBytes );
358 if ( !hGlobalDest )
359 return 0;
361 pGlobalSrc = GlobalLock(hGlobalSrc);
362 pGlobalDest = GlobalLock(hGlobalDest);
363 if ( !pGlobalSrc || !pGlobalDest )
364 return 0;
366 memcpy(pGlobalDest, pGlobalSrc, cBytes);
368 GlobalUnlock(hGlobalSrc);
369 GlobalUnlock(hGlobalDest);
371 return hGlobalDest;
374 /**************************************************************************
375 * CLIPBOARD_GetFormatName
376 * Gets the format name associated with an ID
378 char * CLIPBOARD_GetFormatName(UINT wFormat)
380 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
381 return (lpFormat) ? lpFormat->Name : NULL;
385 /**************************************************************************
386 * CLIPBOARD_RenderFormat
388 static BOOL CLIPBOARD_RenderFormat(LPWINE_CLIPFORMAT lpFormat)
391 * If WINE is not the selection owner, and the format is available
392 * we must ask the driver to render the data to the clipboard cache.
394 TRACE("enter format=%d\n", lpFormat->wFormatID);
395 if ( !USER_Driver.pIsSelectionOwner()
396 && USER_Driver.pIsClipboardFormatAvailable( lpFormat->wFormatID ) )
398 if ( !USER_Driver.pGetClipboardData( lpFormat->wFormatID ) )
399 return FALSE;
402 * If Wine owns the clipboard, and the data is marked for delayed render,
403 * render it now.
405 else if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
407 if( IsWindow(hWndClipOwner) )
409 /* Send a WM_RENDERFORMAT message to notify the owner to render the
410 * data requested into the clipboard.
412 TRACE("Sending WM_RENDERFORMAT message\n");
413 SendMessageW( hWndClipOwner, WM_RENDERFORMAT, (WPARAM)lpFormat->wFormatID, 0 );
415 else
417 WARN("\thWndClipOwner (%04x) is lost!\n",
418 hWndClipOwner);
419 CLIPBOARD_ReleaseOwner();
420 lpFormat->wDataPresent = 0;
421 return FALSE;
425 return (lpFormat->hData16 || lpFormat->hData32) ? TRUE : FALSE;
428 /**************************************************************************
429 * CLIPBOARD_ConvertText
430 * Returns number of required/converted characters - not bytes!
432 static INT CLIPBOARD_ConvertText(WORD src_fmt, void const *src, INT src_size,
433 WORD dst_fmt, void *dst, INT dst_size)
435 UINT cp;
437 if(src_fmt == CF_UNICODETEXT)
439 switch(dst_fmt)
441 case CF_TEXT:
442 cp = CP_ACP;
443 break;
444 case CF_OEMTEXT:
445 cp = CP_OEMCP;
446 break;
447 default:
448 return 0;
450 return WideCharToMultiByte(cp, 0, src, src_size, dst, dst_size, NULL, NULL);
453 if(dst_fmt == CF_UNICODETEXT)
455 switch(src_fmt)
457 case CF_TEXT:
458 cp = CP_ACP;
459 break;
460 case CF_OEMTEXT:
461 cp = CP_OEMCP;
462 break;
463 default:
464 return 0;
466 return MultiByteToWideChar(cp, 0, src, src_size, dst, dst_size);
469 if(!dst_size) return src_size;
471 if(dst_size > src_size) dst_size = src_size;
473 if(src_fmt == CF_TEXT )
474 CharToOemBuffA(src, dst, dst_size);
475 else
476 OemToCharBuffA(src, dst, dst_size);
478 return dst_size;
481 /**************************************************************************
482 * CLIPBOARD_RenderText
484 * Renders text to the clipboard buffer converting between UNIX and DOS formats.
486 * RETURNS: pointer to the WINE_CLIPFORMAT if successful, NULL otherwise
488 * FIXME: Should be a pair of driver functions that convert between OEM text and Windows.
491 static LPWINE_CLIPFORMAT CLIPBOARD_RenderText( UINT wFormat )
493 LPWINE_CLIPFORMAT lpSource = ClipFormats;
494 LPWINE_CLIPFORMAT lpTarget = NULL;
495 BOOL foundData = FALSE;
497 /* Asked for CF_TEXT */
498 if( wFormat == CF_TEXT)
500 if(ClipFormats[CF_TEXT-1].wDataPresent)
502 lpSource = &ClipFormats[CF_TEXT-1];
503 lpTarget = &ClipFormats[CF_TEXT-1];
504 foundData = TRUE;
505 TRACE("\t TEXT -> TEXT\n");
507 else if(ClipFormats[CF_UNICODETEXT-1].wDataPresent)
509 /* Convert UNICODETEXT -> TEXT */
510 lpSource = &ClipFormats[CF_UNICODETEXT-1];
511 lpTarget = &ClipFormats[CF_TEXT-1];
512 foundData = TRUE;
513 TRACE("\tUNICODETEXT -> TEXT\n");
515 else if(ClipFormats[CF_OEMTEXT-1].wDataPresent)
517 /* Convert OEMTEXT -> TEXT */
518 lpSource = &ClipFormats[CF_OEMTEXT-1];
519 lpTarget = &ClipFormats[CF_TEXT-1];
520 foundData = TRUE;
521 TRACE("\tOEMTEXT -> TEXT\n");
524 /* Asked for CF_OEMTEXT */
525 else if( wFormat == CF_OEMTEXT)
527 if(ClipFormats[CF_OEMTEXT-1].wDataPresent)
529 lpSource = &ClipFormats[CF_OEMTEXT-1];
530 lpTarget = &ClipFormats[CF_OEMTEXT-1];
531 foundData = TRUE;
532 TRACE("\tOEMTEXT -> OEMTEXT\n");
534 else if(ClipFormats[CF_UNICODETEXT-1].wDataPresent)
536 /* Convert UNICODETEXT -> OEMTEXT */
537 lpSource = &ClipFormats[CF_UNICODETEXT-1];
538 lpTarget = &ClipFormats[CF_OEMTEXT-1];
539 foundData = TRUE;
540 TRACE("\tUNICODETEXT -> OEMTEXT\n");
542 else if(ClipFormats[CF_TEXT-1].wDataPresent)
544 /* Convert TEXT -> OEMTEXT */
545 lpSource = &ClipFormats[CF_TEXT-1];
546 lpTarget = &ClipFormats[CF_OEMTEXT-1];
547 foundData = TRUE;
548 TRACE("\tTEXT -> OEMTEXT\n");
551 /* Asked for CF_UNICODETEXT */
552 else if( wFormat == CF_UNICODETEXT )
554 if(ClipFormats[CF_UNICODETEXT-1].wDataPresent)
556 lpSource = &ClipFormats[CF_UNICODETEXT-1];
557 lpTarget = &ClipFormats[CF_UNICODETEXT-1];
558 foundData = TRUE;
559 TRACE("\tUNICODETEXT -> UNICODETEXT\n");
561 else if(ClipFormats[CF_TEXT-1].wDataPresent)
563 /* Convert TEXT -> UNICODETEXT */
564 lpSource = &ClipFormats[CF_TEXT-1];
565 lpTarget = &ClipFormats[CF_UNICODETEXT-1];
566 foundData = TRUE;
567 TRACE("\tTEXT -> UNICODETEXT\n");
569 else if(ClipFormats[CF_OEMTEXT-1].wDataPresent)
571 /* Convert OEMTEXT -> UNICODETEXT */
572 lpSource = &ClipFormats[CF_OEMTEXT-1];
573 lpTarget = &ClipFormats[CF_UNICODETEXT-1];
574 foundData = TRUE;
575 TRACE("\tOEMTEXT -> UNICODETEXT\n");
578 if (!foundData)
580 if ((wFormat == CF_TEXT) || (wFormat == CF_OEMTEXT))
582 lpSource = &ClipFormats[CF_UNICODETEXT-1];
583 lpTarget = __lookup_format( ClipFormats, wFormat );
585 else
587 lpSource = __lookup_format( ClipFormats, wFormat );
588 lpTarget = lpSource;
592 /* First render the source text format */
593 if ( !lpSource || !CLIPBOARD_RenderFormat(lpSource) ) return NULL;
595 /* Convert to the desired target text format, if necessary */
596 if( lpTarget != lpSource && !lpTarget->hData16 && !lpTarget->hData32 )
598 INT src_chars, dst_chars, alloc_size;
599 LPCSTR lpstrS;
600 LPSTR lpstrT;
602 if (lpSource->hData32)
604 lpstrS = (LPSTR)GlobalLock(lpSource->hData32);
606 else
608 lpstrS = (LPSTR)GlobalLock16(lpSource->hData16);
611 if( !lpstrS ) return NULL;
613 /* Text always NULL terminated */
614 if(lpSource->wFormatID == CF_UNICODETEXT)
615 src_chars = strlenW((LPCWSTR)lpstrS)+1;
616 else
617 src_chars = strlen(lpstrS)+1;
619 /* Calculate number of characters in the destination buffer */
620 dst_chars = CLIPBOARD_ConvertText(lpSource->wFormatID, lpstrS, src_chars,
621 lpTarget->wFormatID, NULL, 0);
622 if(!dst_chars) return NULL;
624 TRACE("\tconverting from '%s' to '%s', %i chars\n",
625 lpSource->Name, lpTarget->Name, src_chars);
627 /* Convert characters to bytes */
628 if(lpTarget->wFormatID == CF_UNICODETEXT)
629 alloc_size = dst_chars * sizeof(WCHAR);
630 else
631 alloc_size = dst_chars;
633 lpTarget->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, alloc_size);
634 lpstrT = (LPSTR)GlobalLock(lpTarget->hData32);
636 if( lpstrT )
638 CLIPBOARD_ConvertText(lpSource->wFormatID, lpstrS, src_chars,
639 lpTarget->wFormatID, lpstrT, dst_chars);
640 GlobalUnlock(lpTarget->hData32);
642 else
643 lpTarget->hData32 = 0;
645 /* Unlock source */
646 if (lpSource->hData32)
647 GlobalUnlock(lpSource->hData32);
648 else
649 GlobalUnlock16(lpSource->hData16);
652 return (lpTarget->hData16 || lpTarget->hData32) ? lpTarget : NULL;
655 /**************************************************************************
656 * CLIPBOARD_EnumClipboardFormats (internal)
658 static UINT CLIPBOARD_EnumClipboardFormats( UINT wFormat )
660 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
661 BOOL bFormatPresent;
663 if (wFormat == 0) /* start from the beginning */
664 lpFormat = ClipFormats;
665 else
667 /* walk up to the specified format record */
669 if( !(lpFormat = __lookup_format( lpFormat, wFormat )) )
670 return 0;
671 lpFormat = lpFormat->NextFormat; /* right */
674 while(TRUE)
676 if (lpFormat == NULL) return 0;
678 if(CLIPBOARD_IsPresent(lpFormat->wFormatID))
679 break;
681 /* Query the driver if not yet in the cache */
682 if (!USER_Driver.pIsSelectionOwner())
684 if(lpFormat->wFormatID == CF_UNICODETEXT ||
685 lpFormat->wFormatID == CF_TEXT ||
686 lpFormat->wFormatID == CF_OEMTEXT)
688 if(USER_Driver.pIsClipboardFormatAvailable(CF_UNICODETEXT) ||
689 USER_Driver.pIsClipboardFormatAvailable(CF_TEXT) ||
690 USER_Driver.pIsClipboardFormatAvailable(CF_OEMTEXT))
691 bFormatPresent = TRUE;
692 else
693 bFormatPresent = FALSE;
695 else
696 bFormatPresent = USER_Driver.pIsClipboardFormatAvailable(lpFormat->wFormatID);
698 if(bFormatPresent)
699 break;
702 lpFormat = lpFormat->NextFormat;
705 TRACE("Next available format %d\n", lpFormat->wFormatID);
707 return lpFormat->wFormatID;
711 /**************************************************************************
712 * WIN32 Clipboard implementation
713 **************************************************************************/
715 /**************************************************************************
716 * OpenClipboard (USER.137)
718 BOOL16 WINAPI OpenClipboard16( HWND16 hWnd )
720 return OpenClipboard( hWnd );
724 /**************************************************************************
725 * OpenClipboard (USER32.@)
727 * Note: Netscape uses NULL hWnd to open the clipboard.
729 BOOL WINAPI OpenClipboard( HWND hWnd )
731 BOOL bRet;
733 TRACE("(%04x)...\n", hWnd);
735 if (!hClipLock)
737 hClipLock = GetCurrentTask();
739 /* Save current user of the clipboard */
740 hWndClipWindow = hWnd;
741 bCBHasChanged = FALSE;
742 bRet = TRUE;
744 else bRet = FALSE;
746 TRACE(" returning %i\n", bRet);
747 return bRet;
751 /**************************************************************************
752 * CloseClipboard (USER.138)
754 BOOL16 WINAPI CloseClipboard16(void)
756 return CloseClipboard();
760 /**************************************************************************
761 * CloseClipboard (USER32.@)
763 BOOL WINAPI CloseClipboard(void)
765 TRACE("()\n");
767 if (hClipLock == GetCurrentTask())
769 hWndClipWindow = 0;
771 if (bCBHasChanged && hWndViewer) SendMessageW( hWndViewer, WM_DRAWCLIPBOARD, 0, 0 );
772 hClipLock = 0;
774 return TRUE;
778 /**************************************************************************
779 * EmptyClipboard (USER.139)
781 BOOL16 WINAPI EmptyClipboard16(void)
783 return EmptyClipboard();
787 /**************************************************************************
788 * EmptyClipboard (USER32.@)
789 * Empties and acquires ownership of the clipboard
791 BOOL WINAPI EmptyClipboard(void)
793 TRACE("()\n");
795 if (hClipLock != GetCurrentTask())
797 WARN("Clipboard not opened by calling task!\n");
798 return FALSE;
801 /* destroy private objects */
803 if (hWndClipOwner) SendMessageW( hWndClipOwner, WM_DESTROYCLIPBOARD, 0, 0 );
805 /* empty the cache */
806 CLIPBOARD_EmptyCache(TRUE);
808 /* Assign ownership of the clipboard to the current client */
809 hWndClipOwner = hWndClipWindow;
811 /* Save the current task */
812 hTaskClipOwner = GetCurrentTask();
814 /* Tell the driver to acquire the selection */
815 USER_Driver.pAcquireClipboard();
817 return TRUE;
821 /**************************************************************************
822 * GetClipboardOwner (USER.140)
823 * FIXME: Can't return the owner if the clipbard is owned by an external app
825 HWND16 WINAPI GetClipboardOwner16(void)
827 TRACE("()\n");
828 return hWndClipOwner;
832 /**************************************************************************
833 * GetClipboardOwner (USER32.@)
834 * FIXME: Can't return the owner if the clipbard is owned by an external app
836 HWND WINAPI GetClipboardOwner(void)
838 TRACE("()\n");
839 return hWndClipOwner;
843 /**************************************************************************
844 * SetClipboardData (USER.141)
846 HANDLE16 WINAPI SetClipboardData16( UINT16 wFormat, HANDLE16 hData )
848 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
850 TRACE("(%04X, %04x) !\n", wFormat, hData);
852 /* NOTE: If the hData is zero and current owner doesn't match
853 * the window that opened the clipboard then this application
854 * is screwed because WM_RENDERFORMAT will go to the owner.
855 * (to become the owner it must call EmptyClipboard() before
856 * adding new data).
859 if( CLIPBOARD_IsLocked() || !lpFormat ||
860 (!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) )
862 WARN("Invalid hData or clipboard not opened by calling task!\n");
863 return 0;
866 /* Pass on the request to the driver */
867 USER_Driver.pSetClipboardData(wFormat);
869 if ( lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32 )
871 CLIPBOARD_DeleteRecord(lpFormat, TRUE);
873 /* delete existing CF_UNICODETEXT/CF_TEXT/CF_OEMTEXT aliases */
874 if(wFormat == CF_UNICODETEXT)
876 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
877 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
879 else if(wFormat == CF_TEXT)
881 CLIPBOARD_DeleteRecord(&ClipFormats[CF_UNICODETEXT-1], TRUE);
882 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
884 else if(wFormat == CF_OEMTEXT)
886 CLIPBOARD_DeleteRecord(&ClipFormats[CF_UNICODETEXT-1], TRUE);
887 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
891 bCBHasChanged = TRUE;
892 lpFormat->wDataPresent = 1;
893 lpFormat->hData16 = hData; /* 0 is legal, see WM_RENDERFORMAT */
894 lpFormat->hData32 = 0;
896 return lpFormat->hData16;
900 /**************************************************************************
901 * SetClipboardData (USER32.@)
903 HANDLE WINAPI SetClipboardData( UINT wFormat, HANDLE hData )
905 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
907 TRACE("(%08X, %08x) !\n", wFormat, hData);
909 /* NOTE: If the hData is zero and current owner doesn't match
910 * the window that opened the clipboard then this application
911 * is screwed because WM_RENDERFORMAT will go to the owner.
912 * (to become the owner it must call EmptyClipboard() before
913 * adding new data).
916 if( CLIPBOARD_IsLocked() || !lpFormat ||
917 (!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) )
919 WARN("Invalid hData or clipboard not opened by calling task!\n");
920 return 0;
923 /* Tell the driver to acquire the selection */
924 USER_Driver.pAcquireClipboard();
926 if ( lpFormat->wDataPresent &&
927 (lpFormat->hData16 || lpFormat->hData32) )
929 CLIPBOARD_DeleteRecord(lpFormat, TRUE);
931 /* delete existing CF_UNICODETEXT/CF_TEXT/CF_OEMTEXT aliases */
932 if(wFormat == CF_UNICODETEXT)
934 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
935 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
937 else if(wFormat == CF_TEXT)
939 CLIPBOARD_DeleteRecord(&ClipFormats[CF_UNICODETEXT-1], TRUE);
940 CLIPBOARD_DeleteRecord(&ClipFormats[CF_OEMTEXT-1], TRUE);
942 else if(wFormat == CF_OEMTEXT)
944 CLIPBOARD_DeleteRecord(&ClipFormats[CF_UNICODETEXT-1], TRUE);
945 CLIPBOARD_DeleteRecord(&ClipFormats[CF_TEXT-1], TRUE);
949 bCBHasChanged = TRUE;
950 lpFormat->wDataPresent = 1;
951 lpFormat->hDataSrc32 = hData; /* Save the source handle */
954 * Make a shared duplicate if the memory is not shared
955 * TODO: What should be done for non-memory objects
957 if ( CLIPBOARD_IsMemoryObject(wFormat) && hData && !(GlobalFlags(hData) & GMEM_DDESHARE) )
958 lpFormat->hData32 = CLIPBOARD_GlobalDupMem( hData );
959 else
960 lpFormat->hData32 = hData; /* 0 is legal, see WM_RENDERFORMAT */
962 lpFormat->hData16 = 0;
964 return lpFormat->hData32; /* Should we return lpFormat->hDataSrc32 */
968 /**************************************************************************
969 * GetClipboardData (USER.142)
971 HANDLE16 WINAPI GetClipboardData16( UINT16 wFormat )
973 LPWINE_CLIPFORMAT lpRender = ClipFormats;
975 TRACE("(%04X)\n", wFormat);
977 if (CLIPBOARD_IsLocked())
979 WARN("Clipboard not opened by calling task!\n");
980 return 0;
983 if( wFormat == CF_UNICODETEXT || wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
985 lpRender = CLIPBOARD_RenderText(wFormat);
986 if ( !lpRender ) return 0;
988 else
990 lpRender = __lookup_format( ClipFormats, wFormat );
991 if( !lpRender || !CLIPBOARD_RenderFormat(lpRender) ) return 0;
994 /* Convert between 32 -> 16 bit data, if necessary */
995 if( lpRender->hData32 && !lpRender->hData16
996 && CLIPBOARD_IsMemoryObject(wFormat) )
998 int size;
999 if( lpRender->wFormatID == CF_METAFILEPICT )
1000 size = sizeof( METAFILEPICT16 );
1001 else
1002 size = GlobalSize(lpRender->hData32);
1004 lpRender->hData16 = GlobalAlloc16(GMEM_ZEROINIT, size);
1005 if( !lpRender->hData16 )
1006 ERR("(%04X) -- not enough memory in 16b heap\n", wFormat);
1007 else
1009 if( lpRender->wFormatID == CF_METAFILEPICT )
1011 FIXME("\timplement function CopyMetaFilePict32to16\n");
1012 FIXME("\tin the appropriate file.\n");
1013 #ifdef SOMEONE_IMPLEMENTED_ME
1014 CopyMetaFilePict32to16( GlobalLock16(lpRender->hData16),
1015 GlobalLock(lpRender->hData32) );
1016 #endif
1018 else
1020 memcpy( GlobalLock16(lpRender->hData16),
1021 GlobalLock(lpRender->hData32),
1022 size );
1024 GlobalUnlock16(lpRender->hData16);
1025 GlobalUnlock(lpRender->hData32);
1029 TRACE("\treturning %04x (type %i)\n",
1030 lpRender->hData16, lpRender->wFormatID);
1031 return lpRender->hData16;
1035 /**************************************************************************
1036 * GetClipboardData (USER32.@)
1038 HANDLE WINAPI GetClipboardData( UINT wFormat )
1040 LPWINE_CLIPFORMAT lpRender = ClipFormats;
1042 TRACE("(%08X)\n", wFormat);
1044 if (CLIPBOARD_IsLocked())
1046 WARN("Clipboard not opened by calling task!\n");
1047 return 0;
1050 if( wFormat == CF_UNICODETEXT || wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
1052 lpRender = CLIPBOARD_RenderText(wFormat);
1053 if ( !lpRender ) return 0;
1055 else
1057 lpRender = __lookup_format( ClipFormats, wFormat );
1058 if( !lpRender || !CLIPBOARD_RenderFormat(lpRender) ) return 0;
1061 /* Convert between 16 -> 32 bit data, if necessary */
1062 if( lpRender->hData16 && !lpRender->hData32
1063 && CLIPBOARD_IsMemoryObject(wFormat) )
1065 int size;
1066 if( lpRender->wFormatID == CF_METAFILEPICT )
1067 size = sizeof( METAFILEPICT );
1068 else
1069 size = GlobalSize16(lpRender->hData16);
1070 lpRender->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE,
1071 size);
1072 if( lpRender->wFormatID == CF_METAFILEPICT )
1074 FIXME("\timplement function CopyMetaFilePict16to32\n");
1075 FIXME("\tin the appropriate file.\n");
1076 #ifdef SOMEONE_IMPLEMENTED_ME
1077 CopyMetaFilePict16to32( GlobalLock16(lpRender->hData32),
1078 GlobalLock(lpRender->hData16) );
1079 #endif
1081 else
1083 memcpy( GlobalLock(lpRender->hData32),
1084 GlobalLock16(lpRender->hData16),
1085 size );
1087 GlobalUnlock(lpRender->hData32);
1088 GlobalUnlock16(lpRender->hData16);
1091 TRACE("\treturning %04x (type %i)\n",
1092 lpRender->hData32, lpRender->wFormatID);
1093 return lpRender->hData32;
1097 /**************************************************************************
1098 * CountClipboardFormats (USER.143)
1100 INT16 WINAPI CountClipboardFormats16(void)
1102 return CountClipboardFormats();
1106 /**************************************************************************
1107 * CountClipboardFormats (USER32.@)
1109 INT WINAPI CountClipboardFormats(void)
1111 INT FormatCount = 0;
1112 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
1114 TRACE("()\n");
1116 while(TRUE)
1118 if (lpFormat == NULL) break;
1120 if( lpFormat->wFormatID != CF_TEXT ) /* Don't count CF_TEXT */
1123 * The format is available if either:
1124 * 1. The data is already in the cache.
1125 * 2. The selection is not owned by us(WINE) and the data is
1126 * available to the clipboard driver.
1128 if ( lpFormat->wDataPresent ||
1129 ( !USER_Driver.pIsSelectionOwner()
1130 && USER_Driver.pIsClipboardFormatAvailable( lpFormat->wFormatID ) ) )
1132 TRACE("\tdata found for format 0x%04x(%s)\n",
1133 lpFormat->wFormatID, CLIPBOARD_GetFormatName(lpFormat->wFormatID));
1134 FormatCount++;
1138 lpFormat = lpFormat->NextFormat;
1141 /* these are equivalent, adjust the total */
1142 FormatCount += (ClipFormats[CF_UNICODETEXT-1].wDataPresent ||
1143 ClipFormats[CF_TEXT-1].wDataPresent ||
1144 ClipFormats[CF_OEMTEXT-1].wDataPresent) ? 1 : 0;
1146 TRACE("\ttotal %d\n", FormatCount);
1147 return FormatCount;
1150 /**************************************************************************
1151 * EnumClipboardFormats (USER.144)
1153 UINT16 WINAPI EnumClipboardFormats16( UINT16 wFormat )
1155 return EnumClipboardFormats( wFormat );
1159 /**************************************************************************
1160 * EnumClipboardFormats (USER32.@)
1162 UINT WINAPI EnumClipboardFormats( UINT wFormat )
1164 TRACE("(%04X)\n", wFormat);
1166 if (CLIPBOARD_IsLocked())
1168 WARN("Clipboard not opened by calling task!\n");
1169 return 0;
1172 return CLIPBOARD_EnumClipboardFormats(wFormat);
1176 /**************************************************************************
1177 * RegisterClipboardFormatA (USER32.@)
1179 UINT WINAPI RegisterClipboardFormatA( LPCSTR FormatName )
1181 LPWINE_CLIPFORMAT lpNewFormat;
1182 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
1184 if (FormatName == NULL) return 0;
1186 TRACE("('%s') !\n", FormatName);
1188 /* walk format chain to see if it's already registered */
1190 while(TRUE)
1192 if ( !strcmp(lpFormat->Name,FormatName) )
1194 lpFormat->wRefCount++;
1195 return lpFormat->wFormatID;
1198 if ( lpFormat->NextFormat == NULL ) break;
1200 lpFormat = lpFormat->NextFormat;
1203 /* allocate storage for new format entry */
1205 lpNewFormat = (LPWINE_CLIPFORMAT)HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_CLIPFORMAT));
1206 if(lpNewFormat == NULL) {
1207 WARN("No more memory for a new format!\n");
1208 return 0;
1210 lpFormat->NextFormat = lpNewFormat;
1211 lpNewFormat->wFormatID = LastRegFormat;
1212 lpNewFormat->wRefCount = 1;
1214 if (!(lpNewFormat->Name = HeapAlloc(GetProcessHeap(), 0, strlen(FormatName)+1 )))
1216 WARN("No more memory for the new format name!\n");
1217 HeapFree(GetProcessHeap(), 0, lpNewFormat);
1218 return 0;
1220 strcpy( lpNewFormat->Name, FormatName );
1222 lpNewFormat->wDataPresent = 0;
1223 lpNewFormat->hData16 = 0;
1224 lpNewFormat->hDataSrc32 = 0;
1225 lpNewFormat->hData32 = 0;
1226 lpNewFormat->drvData = 0;
1227 lpNewFormat->PrevFormat = lpFormat;
1228 lpNewFormat->NextFormat = NULL;
1230 /* Pass on the registration request to the driver */
1231 USER_Driver.pRegisterClipboardFormat( FormatName );
1233 return LastRegFormat++;
1237 /**************************************************************************
1238 * RegisterClipboardFormat (USER.145)
1240 UINT16 WINAPI RegisterClipboardFormat16( LPCSTR FormatName )
1242 return RegisterClipboardFormatA( FormatName );
1246 /**************************************************************************
1247 * RegisterClipboardFormatW (USER32.@)
1249 UINT WINAPI RegisterClipboardFormatW( LPCWSTR formatName )
1251 LPSTR aFormat = HEAP_strdupWtoA( GetProcessHeap(), 0, formatName );
1252 UINT ret = RegisterClipboardFormatA( aFormat );
1253 HeapFree( GetProcessHeap(), 0, aFormat );
1254 return ret;
1258 /**************************************************************************
1259 * GetClipboardFormatName (USER.146)
1261 INT16 WINAPI GetClipboardFormatName16( UINT16 wFormat, LPSTR retStr, INT16 maxlen )
1263 return GetClipboardFormatNameA( wFormat, retStr, maxlen );
1267 /**************************************************************************
1268 * GetClipboardFormatNameA (USER32.@)
1270 INT WINAPI GetClipboardFormatNameA( UINT wFormat, LPSTR retStr, INT maxlen )
1272 LPWINE_CLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat );
1274 TRACE("(%04X, %p, %d) !\n", wFormat, retStr, maxlen);
1276 if (lpFormat == NULL || lpFormat->Name == NULL ||
1277 lpFormat->wFormatID < CF_REGFORMATBASE) return 0;
1279 TRACE("Name='%s' !\n", lpFormat->Name);
1281 lstrcpynA( retStr, lpFormat->Name, maxlen );
1282 return strlen(retStr);
1286 /**************************************************************************
1287 * GetClipboardFormatNameW (USER32.@)
1289 INT WINAPI GetClipboardFormatNameW( UINT wFormat, LPWSTR retStr, INT maxlen )
1291 INT ret;
1292 LPSTR p = HeapAlloc( GetProcessHeap(), 0, maxlen );
1293 if(p == NULL) return 0; /* FIXME: is this the correct failure value? */
1295 ret = GetClipboardFormatNameA( wFormat, p, maxlen );
1297 if (maxlen > 0 && !MultiByteToWideChar( CP_ACP, 0, p, -1, retStr, maxlen ))
1298 retStr[maxlen-1] = 0;
1299 HeapFree( GetProcessHeap(), 0, p );
1300 return ret;
1304 /**************************************************************************
1305 * SetClipboardViewer (USER.147)
1307 HWND16 WINAPI SetClipboardViewer16( HWND16 hWnd )
1309 TRACE("(%04x)\n", hWnd);
1310 return SetClipboardViewer( hWnd );
1314 /**************************************************************************
1315 * SetClipboardViewer (USER32.@)
1317 HWND WINAPI SetClipboardViewer( HWND hWnd )
1319 HWND hwndPrev = hWndViewer;
1321 TRACE("(%04x): returning %04x\n", hWnd, hwndPrev);
1323 hWndViewer = hWnd;
1324 return hwndPrev;
1328 /**************************************************************************
1329 * GetClipboardViewer (USER.148)
1331 HWND16 WINAPI GetClipboardViewer16(void)
1333 TRACE("()\n");
1334 return hWndViewer;
1338 /**************************************************************************
1339 * GetClipboardViewer (USER32.@)
1341 HWND WINAPI GetClipboardViewer(void)
1343 TRACE("()\n");
1344 return hWndViewer;
1348 /**************************************************************************
1349 * ChangeClipboardChain (USER.149)
1351 BOOL16 WINAPI ChangeClipboardChain16(HWND16 hWnd, HWND16 hWndNext)
1353 return ChangeClipboardChain(hWnd, hWndNext);
1357 /**************************************************************************
1358 * ChangeClipboardChain (USER32.@)
1360 BOOL WINAPI ChangeClipboardChain(HWND hWnd, HWND hWndNext)
1362 BOOL bRet = 0;
1364 FIXME("(0x%04x, 0x%04x): stub?\n", hWnd, hWndNext);
1366 if( hWndViewer )
1367 bRet = !SendMessageW( hWndViewer, WM_CHANGECBCHAIN, (WPARAM)hWnd, (LPARAM)hWndNext );
1368 else
1369 WARN("hWndViewer is lost\n");
1371 if( hWnd == hWndViewer ) hWndViewer = hWndNext;
1373 return bRet;
1377 /**************************************************************************
1378 * IsClipboardFormatAvailable (USER.193)
1380 BOOL16 WINAPI IsClipboardFormatAvailable16( UINT16 wFormat )
1382 return IsClipboardFormatAvailable( wFormat );
1386 /**************************************************************************
1387 * IsClipboardFormatAvailable (USER32.@)
1389 BOOL WINAPI IsClipboardFormatAvailable( UINT wFormat )
1391 BOOL bRet;
1393 if (wFormat == 0) /* Reject this case quickly */
1394 bRet = FALSE;
1395 else
1397 UINT iret = CLIPBOARD_EnumClipboardFormats(wFormat - 1);
1398 if ((wFormat == CF_TEXT) || (wFormat == CF_OEMTEXT) || (wFormat == CF_UNICODETEXT))
1399 bRet = ((iret == CF_TEXT) || (iret == CF_OEMTEXT) || (iret == CF_UNICODETEXT));
1400 else
1401 bRet = iret == wFormat;
1403 TRACE("(%04X)- ret(%d)\n", wFormat, bRet);
1404 return bRet;
1408 /**************************************************************************
1409 * GetOpenClipboardWindow (USER.248)
1410 * FIXME: This wont work if an external app owns the selection
1412 HWND16 WINAPI GetOpenClipboardWindow16(void)
1414 TRACE("()\n");
1415 return hWndClipWindow;
1419 /**************************************************************************
1420 * GetOpenClipboardWindow (USER32.@)
1421 * FIXME: This wont work if an external app owns the selection
1423 HWND WINAPI GetOpenClipboardWindow(void)
1425 TRACE("()\n");
1426 return hWndClipWindow;
1430 /**************************************************************************
1431 * GetPriorityClipboardFormat (USER.402)
1433 INT16 WINAPI GetPriorityClipboardFormat16( UINT16 *lpPriorityList, INT16 nCount)
1435 FIXME("(%p,%d): stub\n", lpPriorityList, nCount );
1436 return 0;
1440 /**************************************************************************
1441 * GetPriorityClipboardFormat (USER32.@)
1443 INT WINAPI GetPriorityClipboardFormat( UINT *lpPriorityList, INT nCount )
1445 int Counter;
1446 TRACE("()\n");
1448 if(CountClipboardFormats() == 0)
1450 return 0;
1453 for(Counter = 0; Counter <= nCount; Counter++)
1455 if(IsClipboardFormatAvailable(*(lpPriorityList+sizeof(INT)*Counter)))
1456 return *(lpPriorityList+sizeof(INT)*Counter);
1459 return -1;
1463 /**************************************************************************
1464 * GetClipboardSequenceNumber (USER32.@)
1465 * Supported on Win2k/Win98
1466 * MSDN: Windows clipboard code keeps a serial number for the clipboard
1467 * for each window station. The number is incremented whenever the
1468 * contents change or are emptied.
1469 * If you do not have WINSTA_ACCESSCLIPBOARD then the function returns 0
1471 DWORD WINAPI GetClipboardSequenceNumber(VOID)
1473 FIXME("Returning 0, see windows/clipboard.c\n");
1474 /* FIXME: Use serial numbers */
1475 return 0;