2 * WINE clipboard function handling
4 * Copyright 1994 Martin Ayotte
10 #include <sys/types.h>
16 #include <X11/Xatom.h>
21 #include "clipboard.h"
25 #define CF_REGFORMATBASE 0xC000
27 typedef struct tagCLIPFORMAT
{
34 struct tagCLIPFORMAT
*PrevFormat
;
35 struct tagCLIPFORMAT
*NextFormat
;
36 } CLIPFORMAT
, *LPCLIPFORMAT
;
38 /* *************************************************************************
42 static HQUEUE16 hqClipLock
= 0;
43 static BOOL32 bCBHasChanged
= FALSE
;
45 static HWND32 hWndClipOwner
= 0; /* current clipboard owner */
46 static HWND32 hWndClipWindow
= 0; /* window that opened clipboard */
47 static HWND32 hWndViewer
= 0; /* start of viewers chain */
49 static WORD LastRegFormat
= CF_REGFORMATBASE
;
51 static Bool selectionWait
= False
;
52 static Bool selectionAcquired
= False
;
53 static Window selectionWindow
= None
;
54 static Window selectionPrevWindow
= None
;
56 static CLIPFORMAT ClipFormats
[16] = {
57 { CF_TEXT
, 1, 0, "Text", (HANDLE16
)NULL
, 0, NULL
, &ClipFormats
[1] },
58 { CF_BITMAP
, 1, 0, "Bitmap", (HANDLE16
)NULL
, 0, &ClipFormats
[0], &ClipFormats
[2] },
59 { CF_METAFILEPICT
, 1, 0, "MetaFile Picture", (HANDLE16
)NULL
, 0, &ClipFormats
[1], &ClipFormats
[3] },
60 { CF_SYLK
, 1, 0, "Sylk", (HANDLE16
)NULL
, 0, &ClipFormats
[2], &ClipFormats
[4] },
61 { CF_DIF
, 1, 0, "DIF", (HANDLE16
)NULL
, 0, &ClipFormats
[3], &ClipFormats
[5] },
62 { CF_TIFF
, 1, 0, "TIFF", (HANDLE16
)NULL
, 0, &ClipFormats
[4], &ClipFormats
[6] },
63 { CF_OEMTEXT
, 1, 0, "OEM Text", (HANDLE16
)NULL
, 0, &ClipFormats
[5], &ClipFormats
[7] },
64 { CF_DIB
, 1, 0, "DIB", (HANDLE16
)NULL
, 0, &ClipFormats
[6], &ClipFormats
[8] },
65 { CF_PALETTE
, 1, 0, "Palette", (HANDLE16
)NULL
, 0, &ClipFormats
[7], &ClipFormats
[9] },
66 { CF_PENDATA
, 1, 0, "PenData", (HANDLE16
)NULL
, 0, &ClipFormats
[8], &ClipFormats
[10] },
67 { CF_RIFF
, 1, 0, "RIFF", (HANDLE16
)NULL
, 0, &ClipFormats
[9], &ClipFormats
[11] },
68 { CF_WAVE
, 1, 0, "Wave", (HANDLE16
)NULL
, 0, &ClipFormats
[10], &ClipFormats
[12] },
69 { CF_OWNERDISPLAY
, 1, 0, "Owner Display", (HANDLE16
)NULL
, 0, &ClipFormats
[11], &ClipFormats
[13] },
70 { CF_DSPTEXT
, 1, 0, "DSPText", (HANDLE16
)NULL
, 0, &ClipFormats
[12], &ClipFormats
[14] },
71 { CF_DSPMETAFILEPICT
, 1, 0, "DSPMetaFile Picture", (HANDLE16
)NULL
, 0, &ClipFormats
[13], &ClipFormats
[15] },
72 { CF_DSPBITMAP
, 1, 0, "DSPBitmap", (HANDLE16
)NULL
, 0, &ClipFormats
[14], NULL
}
75 static LPCLIPFORMAT
__lookup_format( LPCLIPFORMAT lpFormat
, WORD wID
)
79 if (lpFormat
== NULL
||
80 lpFormat
->wFormatID
== wID
) break;
81 lpFormat
= lpFormat
->NextFormat
;
86 /**************************************************************************
87 * CLIPBOARD_CheckSelection
89 * Prevent X selection from being lost when a top level window is
92 static void CLIPBOARD_CheckSelection(WND
* pWnd
)
94 TRACE(clipboard
,"\tchecking %08x\n", (unsigned)pWnd
->window
);
96 if( selectionAcquired
&& selectionWindow
!= None
&&
97 pWnd
->window
== selectionWindow
)
99 selectionPrevWindow
= selectionWindow
;
100 selectionWindow
= None
;
103 selectionWindow
= pWnd
->next
->window
;
104 else if( pWnd
->parent
)
105 if( pWnd
->parent
->child
!= pWnd
)
106 selectionWindow
= pWnd
->parent
->child
->window
;
108 TRACE(clipboard
,"\tswitching selection from %08x to %08x\n",
109 (unsigned)selectionPrevWindow
, (unsigned)selectionWindow
);
111 if( selectionWindow
!= None
)
113 TSXSetSelectionOwner(display
, XA_PRIMARY
, selectionWindow
, CurrentTime
);
114 if( TSXGetSelectionOwner(display
, XA_PRIMARY
) != selectionWindow
)
115 selectionWindow
= None
;
120 /**************************************************************************
121 * CLIPBOARD_ResetLock
123 void CLIPBOARD_ResetLock( HQUEUE16 hqCurrent
, HQUEUE16 hqNew
)
125 if( hqClipLock
== hqCurrent
)
139 /**************************************************************************
140 * CLIPBOARD_ResetOwner
142 * Called from DestroyWindow().
144 void CLIPBOARD_ResetOwner(WND
* pWnd
)
146 LPCLIPFORMAT lpFormat
= ClipFormats
;
148 TRACE(clipboard
,"clipboard owner = %04x, selection = %08x\n",
149 hWndClipOwner
, (unsigned)selectionWindow
);
151 if( pWnd
->hwndSelf
== hWndClipOwner
)
153 SendMessage16(hWndClipOwner
,WM_RENDERALLFORMATS
,0,0L);
155 /* check if all formats were rendered */
159 if( lpFormat
->wDataPresent
&& !lpFormat
->hData
)
161 TRACE(clipboard
,"\tdata missing for clipboard format %i\n",
162 lpFormat
->wFormatID
);
163 lpFormat
->wDataPresent
= 0;
165 lpFormat
= lpFormat
->NextFormat
;
170 /* now try to salvage current selection from being destroyed by X */
172 if( pWnd
->window
) CLIPBOARD_CheckSelection(pWnd
);
175 /**************************************************************************
176 * CLIPBOARD_DeleteRecord
178 static void CLIPBOARD_DeleteRecord(LPCLIPFORMAT lpFormat
, BOOL32 bChange
)
180 if( (lpFormat
->wFormatID
>= CF_GDIOBJFIRST
&&
181 lpFormat
->wFormatID
<= CF_GDIOBJLAST
) || lpFormat
->wFormatID
== CF_BITMAP
)
182 DeleteObject32(lpFormat
->hData
);
183 else if( lpFormat
->wFormatID
== CF_METAFILEPICT
&& lpFormat
->hData
)
185 DeleteMetaFile16( ((METAFILEPICT16
*)GlobalLock16( lpFormat
->hData
))->hMF
);
186 GlobalFree16(lpFormat
->hData
);
188 else if( lpFormat
->hData
)
189 GlobalFree16(lpFormat
->hData
);
191 lpFormat
->wDataPresent
= 0;
194 if( bChange
) bCBHasChanged
= TRUE
;
197 /**************************************************************************
198 * CLIPBOARD_RequestXSelection
200 static BOOL32
CLIPBOARD_RequestXSelection()
202 HWND32 hWnd
= (hWndClipWindow
) ? hWndClipWindow
: GetActiveWindow32();
204 if( !hWnd
) return FALSE
;
206 TRACE(clipboard
,"Requesting selection...\n");
208 /* request data type XA_STRING, later
209 * CLIPBOARD_ReadSelection() will be invoked
210 * from the SelectionNotify event handler */
212 TSXConvertSelection(display
,XA_PRIMARY
,XA_STRING
,
213 TSXInternAtom(display
,"PRIMARY_TEXT",False
),
214 WIN_GetXWindow(hWnd
),CurrentTime
);
216 /* wait until SelectionNotify is processed
218 * FIXME: Use TSXCheckTypedWindowEvent() instead ( same in the
219 * CLIPBOARD_CheckSelection() ).
223 while(selectionWait
) EVENT_WaitNetEvent( TRUE
, FALSE
);
225 /* we treat Unix text as CF_OEMTEXT */
226 TRACE(clipboard
,"\tgot CF_OEMTEXT = %i\n",
227 ClipFormats
[CF_OEMTEXT
-1].wDataPresent
);
229 return (BOOL32
)ClipFormats
[CF_OEMTEXT
-1].wDataPresent
;
232 /**************************************************************************
233 * CLIPBOARD_IsPresent
235 BOOL32
CLIPBOARD_IsPresent(WORD wFormat
)
239 if( wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
)
240 return ClipFormats
[CF_TEXT
-1].wDataPresent
||
241 ClipFormats
[CF_OEMTEXT
-1].wDataPresent
;
244 LPCLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
245 if( lpFormat
) return (lpFormat
->wDataPresent
);
250 /**************************************************************************
251 * OpenClipboard16 (USER.137)
253 BOOL16 WINAPI
OpenClipboard16( HWND16 hWnd
)
255 return OpenClipboard32( hWnd
);
259 /**************************************************************************
260 * OpenClipboard32 (USER32.407)
262 * Note: Netscape uses NULL hWnd to open the clipboard.
264 BOOL32 WINAPI
OpenClipboard32( HWND32 hWnd
)
268 TRACE(clipboard
,"(%04x)...\n", hWnd
);
272 hqClipLock
= GetTaskQueue(0);
273 hWndClipWindow
= hWnd
;
274 bCBHasChanged
= FALSE
;
279 TRACE(clipboard
," returning %i\n", bRet
);
284 /**************************************************************************
285 * CloseClipboard16 (USER.138)
287 BOOL16 WINAPI
CloseClipboard16(void)
289 return CloseClipboard32();
293 /**************************************************************************
294 * CloseClipboard32 (USER32.54)
296 BOOL32 WINAPI
CloseClipboard32(void)
298 TRACE(clipboard
,"!\n");
300 if (hqClipLock
== GetTaskQueue(0))
304 if (bCBHasChanged
&& hWndViewer
)
305 SendMessage16(hWndViewer
, WM_DRAWCLIPBOARD
, 0, 0L);
312 /**************************************************************************
313 * EmptyClipboard16 (USER.139)
315 BOOL16 WINAPI
EmptyClipboard16(void)
317 return EmptyClipboard32();
321 /**************************************************************************
322 * EmptyClipboard32 (USER32.169)
324 BOOL32 WINAPI
EmptyClipboard32(void)
326 LPCLIPFORMAT lpFormat
= ClipFormats
;
328 TRACE(clipboard
,"(void)\n");
330 if (hqClipLock
!= GetTaskQueue(0)) return FALSE
;
332 /* destroy private objects */
335 SendMessage16(hWndClipOwner
, WM_DESTROYCLIPBOARD
, 0, 0L);
339 if ( lpFormat
->wDataPresent
|| lpFormat
->hData
)
340 CLIPBOARD_DeleteRecord( lpFormat
, TRUE
);
342 lpFormat
= lpFormat
->NextFormat
;
345 hWndClipOwner
= hWndClipWindow
;
347 if(selectionAcquired
)
349 selectionAcquired
= False
;
350 selectionPrevWindow
= selectionWindow
;
351 selectionWindow
= None
;
353 TRACE(clipboard
, "\tgiving up selection (spw = %08x)\n",
354 (unsigned)selectionPrevWindow
);
356 TSXSetSelectionOwner(display
, XA_PRIMARY
, None
, CurrentTime
);
362 /**************************************************************************
363 * GetClipboardOwner16 (USER.140)
365 HWND16 WINAPI
GetClipboardOwner16(void)
367 return hWndClipOwner
;
371 /**************************************************************************
372 * GetClipboardOwner32 (USER32.225)
374 HWND32 WINAPI
GetClipboardOwner32(void)
376 return hWndClipOwner
;
380 /**************************************************************************
381 * SetClipboardData16 (USER.141)
383 HANDLE16 WINAPI
SetClipboardData16( UINT16 wFormat
, HANDLE16 hData
)
385 LPCLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
388 TRACE(clipboard
, "(%04X, %04x) !\n", wFormat
, hData
);
390 /* NOTE: If the hData is zero and current owner doesn't match
391 * the window that opened the clipboard then this application
392 * is screwed because WM_RENDERFORMAT will go to the owner
393 * (to become the owner it must call EmptyClipboard() before
397 if( (hqClipLock
!= GetTaskQueue(0)) || !lpFormat
||
398 (!hData
&& (!hWndClipOwner
|| (hWndClipOwner
!= hWndClipWindow
))) ) return 0;
400 /* Acquire X selection if text format */
402 if( !selectionAcquired
&&
403 (wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
) )
405 owner
= WIN_GetXWindow( hWndClipWindow
? hWndClipWindow
: AnyPopup32() );
406 TSXSetSelectionOwner(display
,XA_PRIMARY
,owner
,CurrentTime
);
407 if( TSXGetSelectionOwner(display
,XA_PRIMARY
) == owner
)
409 selectionAcquired
= True
;
410 selectionWindow
= owner
;
412 TRACE(clipboard
,"Grabbed X selection, owner=(%08x)\n",
417 if ( lpFormat
->wDataPresent
|| lpFormat
->hData
)
419 CLIPBOARD_DeleteRecord(lpFormat
, TRUE
);
421 /* delete existing CF_TEXT/CF_OEMTEXT aliases */
423 if( wFormat
== CF_TEXT
&& ClipFormats
[CF_OEMTEXT
-1].hData
424 && !ClipFormats
[CF_OEMTEXT
-1].wDataPresent
)
425 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
426 if( wFormat
== CF_OEMTEXT
&& ClipFormats
[CF_TEXT
-1].hData
427 && !ClipFormats
[CF_TEXT
-1].wDataPresent
)
428 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
431 bCBHasChanged
= TRUE
;
432 lpFormat
->wDataPresent
= 1;
433 lpFormat
->hData
= hData
; /* 0 is legal, see WM_RENDERFORMAT */
435 return lpFormat
->hData
;
439 /**************************************************************************
440 * SetClipboardData32 (USER32.470)
442 HANDLE32 WINAPI
SetClipboardData32( UINT32 wFormat
, HANDLE32 hData
)
444 FIXME(clipboard
, "(%d,%d): stub\n", wFormat
, hData
);
449 /**************************************************************************
450 * CLIPBOARD_RenderFormat
452 static BOOL32
CLIPBOARD_RenderFormat(LPCLIPFORMAT lpFormat
)
454 if( lpFormat
->wDataPresent
&& !lpFormat
->hData
)
455 if( IsWindow32(hWndClipOwner
) )
456 SendMessage16(hWndClipOwner
,WM_RENDERFORMAT
,
457 (WPARAM16
)lpFormat
->wFormatID
,0L);
460 WARN(clipboard
, "\thWndClipOwner (%04x) is lost!\n",
462 hWndClipOwner
= 0; lpFormat
->wDataPresent
= 0;
465 return (lpFormat
->hData
) ? TRUE
: FALSE
;
468 /**************************************************************************
469 * CLIPBOARD_RenderText
471 * Convert text between UNIX and DOS formats.
473 static BOOL32
CLIPBOARD_RenderText(LPCLIPFORMAT lpTarget
, LPCLIPFORMAT lpSource
)
475 UINT16 size
= GlobalSize16( lpSource
->hData
);
476 LPCSTR lpstrS
= (LPSTR
)GlobalLock16(lpSource
->hData
);
479 if( !lpstrS
) return FALSE
;
480 TRACE(clipboard
,"\tconverting from '%s' to '%s', %i chars\n",
481 lpSource
->Name
, lpTarget
->Name
, size
);
483 lpTarget
->hData
= GlobalAlloc16(GMEM_ZEROINIT
, size
);
484 lpstrT
= (LPSTR
)GlobalLock16(lpTarget
->hData
);
488 if( lpSource
->wFormatID
== CF_TEXT
)
489 CharToOemBuff32A(lpstrS
, lpstrT
, size
);
491 OemToCharBuff32A(lpstrS
, lpstrT
, size
);
492 TRACE(clipboard
,"\tgot %s\n", lpstrT
);
500 /**************************************************************************
501 * GetClipboardData16 (USER.142)
503 HANDLE16 WINAPI
GetClipboardData16( UINT16 wFormat
)
505 LPCLIPFORMAT lpRender
= ClipFormats
;
506 LPCLIPFORMAT lpUpdate
= NULL
;
508 if (hqClipLock
!= GetTaskQueue(0)) return 0;
510 TRACE(clipboard
,"(%04X)\n", wFormat
);
512 if( wFormat
== CF_TEXT
&& !lpRender
[CF_TEXT
-1].wDataPresent
513 && lpRender
[CF_OEMTEXT
-1].wDataPresent
)
515 lpRender
= &ClipFormats
[CF_OEMTEXT
-1];
516 lpUpdate
= &ClipFormats
[CF_TEXT
-1];
518 TRACE(clipboard
,"\tOEMTEXT -> TEXT\n");
520 else if( wFormat
== CF_OEMTEXT
&& !lpRender
[CF_OEMTEXT
-1].wDataPresent
521 && lpRender
[CF_TEXT
-1].wDataPresent
)
523 lpRender
= &ClipFormats
[CF_TEXT
-1];
524 lpUpdate
= &ClipFormats
[CF_OEMTEXT
-1];
526 TRACE(clipboard
,"\tTEXT -> OEMTEXT\n");
530 lpRender
= __lookup_format( ClipFormats
, wFormat
);
534 if( !lpRender
|| !CLIPBOARD_RenderFormat(lpRender
) ) return 0;
535 if( lpUpdate
!= lpRender
&& !lpUpdate
->hData
)
536 CLIPBOARD_RenderText(lpUpdate
, lpRender
);
538 TRACE(clipboard
,"\treturning %04x (type %i)\n",
539 lpUpdate
->hData
, lpUpdate
->wFormatID
);
540 return lpUpdate
->hData
;
544 /**************************************************************************
545 * GetClipboardData32 (USER32.222)
547 HANDLE32 WINAPI
GetClipboardData32( UINT32 wFormat
)
549 FIXME(clipboard
, "(%d): stub\n", wFormat
);
553 /**************************************************************************
554 * CountClipboardFormats16 (USER.143)
556 INT16 WINAPI
CountClipboardFormats16(void)
558 return CountClipboardFormats32();
562 /**************************************************************************
563 * CountClipboardFormats32 (USER32.63)
565 INT32 WINAPI
CountClipboardFormats32(void)
567 INT32 FormatCount
= 0;
568 LPCLIPFORMAT lpFormat
= ClipFormats
;
570 TRACE(clipboard
,"(void)\n");
572 if( !selectionAcquired
) CLIPBOARD_RequestXSelection();
574 FormatCount
+= abs(lpFormat
[CF_TEXT
-1].wDataPresent
-
575 lpFormat
[CF_OEMTEXT
-1].wDataPresent
);
579 if (lpFormat
== NULL
) break;
580 if (lpFormat
->wDataPresent
)
582 TRACE(clipboard
, "\tdata found for format %i\n", lpFormat
->wFormatID
);
585 lpFormat
= lpFormat
->NextFormat
;
588 TRACE(clipboard
,"\ttotal %d\n", FormatCount
);
593 /**************************************************************************
594 * EnumClipboardFormats16 (USER.144)
596 UINT16 WINAPI
EnumClipboardFormats16( UINT16 wFormat
)
598 return EnumClipboardFormats32( wFormat
);
602 /**************************************************************************
603 * EnumClipboardFormats32 (USER32.179)
605 UINT32 WINAPI
EnumClipboardFormats32( UINT32 wFormat
)
607 LPCLIPFORMAT lpFormat
= ClipFormats
;
609 TRACE(clipboard
,"(%04X)\n", wFormat
);
611 if( hqClipLock
!= GetTaskQueue(0) ) return 0;
613 if( (!wFormat
|| wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
)
614 && !selectionAcquired
) CLIPBOARD_RequestXSelection();
617 if (lpFormat
->wDataPresent
|| ClipFormats
[CF_OEMTEXT
-1].wDataPresent
)
618 return lpFormat
->wFormatID
;
620 wFormat
= lpFormat
->wFormatID
; /* and CF_TEXT is not available */
622 /* walk up to the specified format record */
624 if( !(lpFormat
= __lookup_format( lpFormat
, wFormat
)) ) return 0;
626 /* find next format with available data */
628 lpFormat
= lpFormat
->NextFormat
;
631 if (lpFormat
== NULL
) return 0;
632 if (lpFormat
->wDataPresent
|| (lpFormat
->wFormatID
== CF_OEMTEXT
&&
633 ClipFormats
[CF_TEXT
-1].wDataPresent
))
635 lpFormat
= lpFormat
->NextFormat
;
638 return lpFormat
->wFormatID
;
642 /**************************************************************************
643 * RegisterClipboardFormat16 (USER.145)
645 UINT16 WINAPI
RegisterClipboardFormat16( LPCSTR FormatName
)
647 LPCLIPFORMAT lpNewFormat
;
648 LPCLIPFORMAT lpFormat
= ClipFormats
;
650 if (FormatName
== NULL
) return 0;
652 TRACE(clipboard
,"('%s') !\n", FormatName
);
654 /* walk format chain to see if it's already registered */
658 if ( !strcmp(lpFormat
->Name
,FormatName
) )
660 lpFormat
->wRefCount
++;
661 return lpFormat
->wFormatID
;
664 if ( lpFormat
->NextFormat
== NULL
) break;
666 lpFormat
= lpFormat
->NextFormat
;
669 /* allocate storage for new format entry */
671 lpNewFormat
= (LPCLIPFORMAT
)xmalloc(sizeof(CLIPFORMAT
));
672 lpFormat
->NextFormat
= lpNewFormat
;
673 lpNewFormat
->wFormatID
= LastRegFormat
;
674 lpNewFormat
->wRefCount
= 1;
676 lpNewFormat
->Name
= (LPSTR
)xmalloc(strlen(FormatName
) + 1);
677 strcpy(lpNewFormat
->Name
, FormatName
);
679 lpNewFormat
->wDataPresent
= 0;
680 lpNewFormat
->hData
= 0;
681 lpNewFormat
->BufSize
= 0;
682 lpNewFormat
->PrevFormat
= lpFormat
;
683 lpNewFormat
->NextFormat
= NULL
;
685 return LastRegFormat
++;
689 /**************************************************************************
690 * RegisterClipboardFormat32A (USER32.431)
692 UINT32 WINAPI
RegisterClipboardFormat32A( LPCSTR formatName
)
694 return RegisterClipboardFormat16( formatName
);
698 /**************************************************************************
699 * RegisterClipboardFormat32W (USER32.432)
701 UINT32 WINAPI
RegisterClipboardFormat32W( LPCWSTR formatName
)
703 LPSTR aFormat
= HEAP_strdupWtoA( GetProcessHeap(), 0, formatName
);
704 UINT32 ret
= RegisterClipboardFormat32A( aFormat
);
705 HeapFree( GetProcessHeap(), 0, aFormat
);
709 /**************************************************************************
710 * GetClipboardFormatName16 (USER.146)
712 INT16 WINAPI
GetClipboardFormatName16( UINT16 wFormat
, LPSTR retStr
, INT16 maxlen
)
714 return GetClipboardFormatName32A( wFormat
, retStr
, maxlen
);
718 /**************************************************************************
719 * GetClipboardFormatName32A (USER32.223)
721 INT32 WINAPI
GetClipboardFormatName32A( UINT32 wFormat
, LPSTR retStr
, INT32 maxlen
)
723 LPCLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
725 TRACE(clipboard
, "(%04X, %p, %d) !\n", wFormat
, retStr
, maxlen
);
727 if (lpFormat
== NULL
|| lpFormat
->Name
== NULL
||
728 lpFormat
->wFormatID
< CF_REGFORMATBASE
) return 0;
730 TRACE(clipboard
, "Name='%s' !\n", lpFormat
->Name
);
732 lstrcpyn32A( retStr
, lpFormat
->Name
, maxlen
);
733 return strlen(retStr
);
737 /**************************************************************************
738 * GetClipboardFormatName32W (USER32.224)
740 INT32 WINAPI
GetClipboardFormatName32W( UINT32 wFormat
, LPWSTR retStr
, INT32 maxlen
)
742 LPSTR p
= HEAP_xalloc( GetProcessHeap(), 0, maxlen
);
743 INT32 ret
= GetClipboardFormatName32A( wFormat
, p
, maxlen
);
744 lstrcpynAtoW( retStr
, p
, maxlen
);
745 HeapFree( GetProcessHeap(), 0, p
);
750 /**************************************************************************
751 * SetClipboardViewer16 (USER.147)
753 HWND16 WINAPI
SetClipboardViewer16( HWND16 hWnd
)
755 return SetClipboardViewer32( hWnd
);
759 /**************************************************************************
760 * SetClipboardViewer32 (USER32.471)
762 HWND32 WINAPI
SetClipboardViewer32( HWND32 hWnd
)
764 HWND32 hwndPrev
= hWndViewer
;
766 TRACE(clipboard
,"(%04x): returning %04x\n", hWnd
, hwndPrev
);
773 /**************************************************************************
774 * GetClipboardViewer16 (USER.148)
776 HWND16 WINAPI
GetClipboardViewer16(void)
782 /**************************************************************************
783 * GetClipboardViewer32 (USER32.226)
785 HWND32 WINAPI
GetClipboardViewer32(void)
791 /**************************************************************************
792 * ChangeClipboardChain16 (USER.149)
794 BOOL16 WINAPI
ChangeClipboardChain16(HWND16 hWnd
, HWND16 hWndNext
)
796 return ChangeClipboardChain32(hWnd
, hWndNext
);
799 /**************************************************************************
800 * ChangeClipboardChain32 (USER32.22)
802 BOOL32 WINAPI
ChangeClipboardChain32(HWND32 hWnd
, HWND32 hWndNext
)
806 FIXME(clipboard
, "(0x%04x, 0x%04x): stub?\n", hWnd
, hWndNext
);
809 bRet
= !SendMessage16( hWndViewer
, WM_CHANGECBCHAIN
,
810 (WPARAM16
)hWnd
, (LPARAM
)hWndNext
);
812 WARN(clipboard
, "hWndViewer is lost\n");
814 if( hWnd
== hWndViewer
) hWndViewer
= hWndNext
;
821 /**************************************************************************
822 * IsClipboardFormatAvailable16 (USER.193)
824 BOOL16 WINAPI
IsClipboardFormatAvailable16( UINT16 wFormat
)
826 return IsClipboardFormatAvailable32( wFormat
);
830 /**************************************************************************
831 * IsClipboardFormatAvailable32 (USER32.340)
833 BOOL32 WINAPI
IsClipboardFormatAvailable32( UINT32 wFormat
)
835 TRACE(clipboard
,"(%04X) !\n", wFormat
);
837 if( (wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
) &&
838 !selectionAcquired
) CLIPBOARD_RequestXSelection();
840 return CLIPBOARD_IsPresent(wFormat
);
844 /**************************************************************************
845 * GetOpenClipboardWindow16 (USER.248)
847 HWND16 WINAPI
GetOpenClipboardWindow16(void)
849 return hWndClipWindow
;
853 /**************************************************************************
854 * GetOpenClipboardWindow32 (USER32.277)
856 HWND32 WINAPI
GetOpenClipboardWindow32(void)
858 return hWndClipWindow
;
862 /**************************************************************************
863 * GetPriorityClipboardFormat16 (USER.402)
865 INT16 WINAPI
GetPriorityClipboardFormat16( UINT16
*lpPriorityList
, INT16 nCount
)
867 FIXME(clipboard
, "(%p,%d): stub\n", lpPriorityList
, nCount
);
872 /**************************************************************************
873 * GetPriorityClipboardFormat32 (USER32.279)
875 INT32 WINAPI
GetPriorityClipboardFormat32( UINT32
*lpPriorityList
, INT32 nCount
)
879 if(CountClipboardFormats32() == 0)
884 for(Counter
= 0; Counter
<= nCount
; Counter
++)
886 if(IsClipboardFormatAvailable32(*(lpPriorityList
+sizeof(INT32
)*Counter
)))
887 return *(lpPriorityList
+sizeof(INT32
)*Counter
);
894 /**************************************************************************
895 * CLIPBOARD_ReadSelection
897 * Called from the SelectionNotify event handler.
899 void CLIPBOARD_ReadSelection(Window w
,Atom prop
)
902 LPCLIPFORMAT lpFormat
= ClipFormats
;
904 TRACE(clipboard
,"ReadSelection callback\n");
908 Atom atype
=AnyPropertyType
;
910 unsigned long nitems
,remain
;
911 unsigned char* val
=NULL
;
913 TRACE(clipboard
,"\tgot property %s\n",TSXGetAtomName(display
,prop
));
915 /* TODO: Properties longer than 64K */
917 if(TSXGetWindowProperty(display
,w
,prop
,0,0x3FFF,True
,XA_STRING
,
918 &atype
, &aformat
, &nitems
, &remain
, &val
) != Success
)
919 WARN(clipboard
, "\tcouldn't read property\n");
922 TRACE(clipboard
,"\tType %s,Format %d,nitems %ld,value %s\n",
923 TSXGetAtomName(display
,atype
),aformat
,nitems
,val
);
925 if(atype
== XA_STRING
&& aformat
== 8)
930 TRACE(clipboard
,"\tselection is '%s'\n",val
);
932 for(i
=0; i
<= nitems
; i
++)
933 if( val
[i
] == '\n' ) inlcount
++;
937 hText
=GlobalAlloc16(GMEM_MOVEABLE
, nitems
+ inlcount
+ 1);
938 if( (lpstr
= (char*)GlobalLock16(hText
)) )
939 for(i
=0,inlcount
=0; i
<= nitems
; i
++)
941 if( val
[i
] == '\n' ) lpstr
[inlcount
++]='\r';
942 lpstr
[inlcount
++]=val
[i
];
951 /* delete previous CF_TEXT and CF_OEMTEXT data */
955 lpFormat
= &ClipFormats
[CF_TEXT
-1];
956 if (lpFormat
->wDataPresent
|| lpFormat
->hData
)
957 CLIPBOARD_DeleteRecord(lpFormat
, !(hWndClipWindow
));
958 lpFormat
= &ClipFormats
[CF_OEMTEXT
-1];
959 if (lpFormat
->wDataPresent
|| lpFormat
->hData
)
960 CLIPBOARD_DeleteRecord(lpFormat
, !(hWndClipWindow
));
962 lpFormat
->wDataPresent
= 1;
963 lpFormat
->hData
= hText
;
969 /**************************************************************************
970 * CLIPBOARD_ReleaseSelection
972 * Wine might have lost XA_PRIMARY selection because of
973 * EmptyClipboard() or other client.
975 void CLIPBOARD_ReleaseSelection(Window w
, HWND32 hwnd
)
977 /* w is the window that lost selection,
979 * selectionPrevWindow is nonzero if CheckSelection() was called.
982 TRACE(clipboard
,"\tevent->window = %08x (sw = %08x, spw=%08x)\n",
983 (unsigned)w
, (unsigned)selectionWindow
, (unsigned)selectionPrevWindow
);
985 if( selectionAcquired
)
986 if( w
== selectionWindow
|| selectionPrevWindow
== None
)
988 /* alright, we really lost it */
990 selectionAcquired
= False
;
991 selectionWindow
= None
;
993 /* but we'll keep existing data for internal use */
995 else if( w
== selectionPrevWindow
)
997 w
= TSXGetSelectionOwner(display
, XA_PRIMARY
);
999 TSXSetSelectionOwner(display
, XA_PRIMARY
, selectionWindow
, CurrentTime
);
1002 selectionPrevWindow
= None
;