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
;
37 } CLIPFORMAT
, *LPCLIPFORMAT
;
39 /* *************************************************************************
43 static HQUEUE16 hqClipLock
= 0;
44 static BOOL32 bCBHasChanged
= FALSE
;
46 static HWND32 hWndClipOwner
= 0; /* current clipboard owner */
47 static HWND32 hWndClipWindow
= 0; /* window that opened clipboard */
48 static HWND32 hWndViewer
= 0; /* start of viewers chain */
50 static WORD LastRegFormat
= CF_REGFORMATBASE
;
52 static Bool selectionWait
= False
;
53 static Bool selectionAcquired
= False
;
54 static Window selectionWindow
= None
;
55 static Window selectionPrevWindow
= None
;
57 static CLIPFORMAT ClipFormats
[16] = {
58 { CF_TEXT
, 1, 0, "Text", (HANDLE32
)NULL
, 0, NULL
, &ClipFormats
[1] , (HANDLE16
)NULL
},
59 { CF_BITMAP
, 1, 0, "Bitmap", (HANDLE32
)NULL
, 0, &ClipFormats
[0], &ClipFormats
[2] , (HANDLE16
)NULL
},
60 { CF_METAFILEPICT
, 1, 0, "MetaFile Picture", (HANDLE32
)NULL
, 0, &ClipFormats
[1], &ClipFormats
[3] , (HANDLE16
)NULL
},
61 { CF_SYLK
, 1, 0, "Sylk", (HANDLE32
)NULL
, 0, &ClipFormats
[2], &ClipFormats
[4] , (HANDLE16
)NULL
},
62 { CF_DIF
, 1, 0, "DIF", (HANDLE32
)NULL
, 0, &ClipFormats
[3], &ClipFormats
[5] , (HANDLE16
)NULL
},
63 { CF_TIFF
, 1, 0, "TIFF", (HANDLE32
)NULL
, 0, &ClipFormats
[4], &ClipFormats
[6] , (HANDLE16
)NULL
},
64 { CF_OEMTEXT
, 1, 0, "OEM Text", (HANDLE32
)NULL
, 0, &ClipFormats
[5], &ClipFormats
[7] , (HANDLE16
)NULL
},
65 { CF_DIB
, 1, 0, "DIB", (HANDLE32
)NULL
, 0, &ClipFormats
[6], &ClipFormats
[8] , (HANDLE16
)NULL
},
66 { CF_PALETTE
, 1, 0, "Palette", (HANDLE32
)NULL
, 0, &ClipFormats
[7], &ClipFormats
[9] , (HANDLE16
)NULL
},
67 { CF_PENDATA
, 1, 0, "PenData", (HANDLE32
)NULL
, 0, &ClipFormats
[8], &ClipFormats
[10] , (HANDLE16
)NULL
},
68 { CF_RIFF
, 1, 0, "RIFF", (HANDLE32
)NULL
, 0, &ClipFormats
[9], &ClipFormats
[11] , (HANDLE16
)NULL
},
69 { CF_WAVE
, 1, 0, "Wave", (HANDLE32
)NULL
, 0, &ClipFormats
[10], &ClipFormats
[12] , (HANDLE16
)NULL
},
70 { CF_OWNERDISPLAY
, 1, 0, "Owner Display", (HANDLE32
)NULL
, 0, &ClipFormats
[11], &ClipFormats
[13] , (HANDLE16
)NULL
},
71 { CF_DSPTEXT
, 1, 0, "DSPText", (HANDLE32
)NULL
, 0, &ClipFormats
[12], &ClipFormats
[14] , (HANDLE16
)NULL
},
72 { CF_DSPMETAFILEPICT
, 1, 0, "DSPMetaFile Picture", (HANDLE32
)NULL
, 0, &ClipFormats
[13], &ClipFormats
[15] , (HANDLE16
)NULL
},
73 { CF_DSPBITMAP
, 1, 0, "DSPBitmap", (HANDLE32
)NULL
, 0, &ClipFormats
[14], NULL
, (HANDLE16
)NULL
}
76 static LPCLIPFORMAT
__lookup_format( LPCLIPFORMAT lpFormat
, WORD wID
)
80 if (lpFormat
== NULL
||
81 lpFormat
->wFormatID
== wID
) break;
82 lpFormat
= lpFormat
->NextFormat
;
87 /**************************************************************************
88 * CLIPBOARD_CheckSelection
90 * Prevent X selection from being lost when a top level window is
93 static void CLIPBOARD_CheckSelection(WND
* pWnd
)
95 TRACE(clipboard
,"\tchecking %08x\n", (unsigned)pWnd
->window
);
97 if( selectionAcquired
&& selectionWindow
!= None
&&
98 pWnd
->window
== selectionWindow
)
100 selectionPrevWindow
= selectionWindow
;
101 selectionWindow
= None
;
104 selectionWindow
= pWnd
->next
->window
;
105 else if( pWnd
->parent
)
106 if( pWnd
->parent
->child
!= pWnd
)
107 selectionWindow
= pWnd
->parent
->child
->window
;
109 TRACE(clipboard
,"\tswitching selection from %08x to %08x\n",
110 (unsigned)selectionPrevWindow
, (unsigned)selectionWindow
);
112 if( selectionWindow
!= None
)
114 TSXSetSelectionOwner(display
, XA_PRIMARY
, selectionWindow
, CurrentTime
);
115 if( TSXGetSelectionOwner(display
, XA_PRIMARY
) != selectionWindow
)
116 selectionWindow
= None
;
121 /**************************************************************************
122 * CLIPBOARD_ResetLock
124 void CLIPBOARD_ResetLock( HQUEUE16 hqCurrent
, HQUEUE16 hqNew
)
126 if( hqClipLock
== hqCurrent
)
140 /**************************************************************************
141 * CLIPBOARD_ResetOwner
143 * Called from DestroyWindow().
145 void CLIPBOARD_ResetOwner(WND
* pWnd
)
147 LPCLIPFORMAT lpFormat
= ClipFormats
;
149 TRACE(clipboard
,"clipboard owner = %04x, selection = %08x\n",
150 hWndClipOwner
, (unsigned)selectionWindow
);
152 if( pWnd
->hwndSelf
== hWndClipOwner
)
154 SendMessage16(hWndClipOwner
,WM_RENDERALLFORMATS
,0,0L);
156 /* check if all formats were rendered */
160 if( lpFormat
->wDataPresent
&& !lpFormat
->hData16
&& !lpFormat
->hData32
)
162 TRACE(clipboard
,"\tdata missing for clipboard format %i\n",
163 lpFormat
->wFormatID
);
164 lpFormat
->wDataPresent
= 0;
166 lpFormat
= lpFormat
->NextFormat
;
171 /* now try to salvage current selection from being destroyed by X */
173 if( pWnd
->window
) CLIPBOARD_CheckSelection(pWnd
);
176 /**************************************************************************
177 * CLIPBOARD_DeleteRecord
179 static void CLIPBOARD_DeleteRecord(LPCLIPFORMAT lpFormat
, BOOL32 bChange
)
181 if( (lpFormat
->wFormatID
>= CF_GDIOBJFIRST
&&
182 lpFormat
->wFormatID
<= CF_GDIOBJLAST
) || lpFormat
->wFormatID
== CF_BITMAP
)
184 if (lpFormat
->hData32
)
185 DeleteObject32(lpFormat
->hData32
);
186 if (lpFormat
->hData16
)
187 DeleteObject16(lpFormat
->hData16
);
189 else if( lpFormat
->wFormatID
== CF_METAFILEPICT
)
191 if (lpFormat
->hData32
)
193 DeleteMetaFile32( ((METAFILEPICT32
*)GlobalLock32( lpFormat
->hData32
))->hMF
);
194 GlobalFree32(lpFormat
->hData32
);
195 if (lpFormat
->hData16
)
196 /* HMETAFILE16 and HMETAFILE32 are apparently the same thing,
197 and a shallow copy is enough to share a METAFILEPICT
198 structure between 16bit and 32bit clipboards. The MetaFile
199 should of course only be deleted once. */
200 GlobalFree16(lpFormat
->hData16
);
202 else if (lpFormat
->hData16
)
204 DeleteMetaFile16( ((METAFILEPICT16
*)GlobalLock16( lpFormat
->hData16
))->hMF
);
205 GlobalFree16(lpFormat
->hData16
);
210 if (lpFormat
->hData32
)
211 GlobalFree32(lpFormat
->hData32
);
212 if (lpFormat
->hData16
)
213 GlobalFree16(lpFormat
->hData16
);
216 lpFormat
->wDataPresent
= 0;
217 lpFormat
->hData16
= 0;
218 lpFormat
->hData32
= 0;
220 if( bChange
) bCBHasChanged
= TRUE
;
223 /**************************************************************************
224 * CLIPBOARD_RequestXSelection
226 static BOOL32
CLIPBOARD_RequestXSelection()
228 HWND32 hWnd
= (hWndClipWindow
) ? hWndClipWindow
: GetActiveWindow32();
230 if( !hWnd
) return FALSE
;
232 TRACE(clipboard
,"Requesting selection...\n");
234 /* request data type XA_STRING, later
235 * CLIPBOARD_ReadSelection() will be invoked
236 * from the SelectionNotify event handler */
238 TSXConvertSelection(display
,XA_PRIMARY
,XA_STRING
,
239 TSXInternAtom(display
,"PRIMARY_TEXT",False
),
240 WIN_GetXWindow(hWnd
),CurrentTime
);
242 /* wait until SelectionNotify is processed
244 * FIXME: Use TSXCheckTypedWindowEvent() instead ( same in the
245 * CLIPBOARD_CheckSelection() ).
249 while(selectionWait
) EVENT_WaitNetEvent( TRUE
, FALSE
);
251 /* we treat Unix text as CF_OEMTEXT */
252 TRACE(clipboard
,"\tgot CF_OEMTEXT = %i\n",
253 ClipFormats
[CF_OEMTEXT
-1].wDataPresent
);
255 return (BOOL32
)ClipFormats
[CF_OEMTEXT
-1].wDataPresent
;
258 /**************************************************************************
259 * CLIPBOARD_IsPresent
261 BOOL32
CLIPBOARD_IsPresent(WORD wFormat
)
265 if( wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
)
266 return ClipFormats
[CF_TEXT
-1].wDataPresent
||
267 ClipFormats
[CF_OEMTEXT
-1].wDataPresent
;
270 LPCLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
271 if( lpFormat
) return (lpFormat
->wDataPresent
);
276 /**************************************************************************
277 * OpenClipboard16 (USER.137)
279 BOOL16 WINAPI
OpenClipboard16( HWND16 hWnd
)
281 return OpenClipboard32( hWnd
);
285 /**************************************************************************
286 * OpenClipboard32 (USER32.407)
288 * Note: Netscape uses NULL hWnd to open the clipboard.
290 BOOL32 WINAPI
OpenClipboard32( HWND32 hWnd
)
294 TRACE(clipboard
,"(%04x)...\n", hWnd
);
298 hqClipLock
= GetTaskQueue(0);
299 hWndClipWindow
= hWnd
;
300 bCBHasChanged
= FALSE
;
305 TRACE(clipboard
," returning %i\n", bRet
);
310 /**************************************************************************
311 * CloseClipboard16 (USER.138)
313 BOOL16 WINAPI
CloseClipboard16(void)
315 return CloseClipboard32();
319 /**************************************************************************
320 * CloseClipboard32 (USER32.54)
322 BOOL32 WINAPI
CloseClipboard32(void)
324 TRACE(clipboard
,"!\n");
326 if (hqClipLock
== GetTaskQueue(0))
330 if (bCBHasChanged
&& hWndViewer
)
331 SendMessage16(hWndViewer
, WM_DRAWCLIPBOARD
, 0, 0L);
338 /**************************************************************************
339 * EmptyClipboard16 (USER.139)
341 BOOL16 WINAPI
EmptyClipboard16(void)
343 return EmptyClipboard32();
347 /**************************************************************************
348 * EmptyClipboard32 (USER32.169)
350 BOOL32 WINAPI
EmptyClipboard32(void)
352 LPCLIPFORMAT lpFormat
= ClipFormats
;
354 TRACE(clipboard
,"(void)\n");
356 if (hqClipLock
!= GetTaskQueue(0)) return FALSE
;
358 /* destroy private objects */
361 SendMessage16(hWndClipOwner
, WM_DESTROYCLIPBOARD
, 0, 0L);
365 if ( lpFormat
->wDataPresent
|| lpFormat
->hData16
|| lpFormat
->hData32
)
366 CLIPBOARD_DeleteRecord( lpFormat
, TRUE
);
368 lpFormat
= lpFormat
->NextFormat
;
371 hWndClipOwner
= hWndClipWindow
;
373 if(selectionAcquired
)
375 selectionAcquired
= False
;
376 selectionPrevWindow
= selectionWindow
;
377 selectionWindow
= None
;
379 TRACE(clipboard
, "\tgiving up selection (spw = %08x)\n",
380 (unsigned)selectionPrevWindow
);
382 TSXSetSelectionOwner(display
, XA_PRIMARY
, None
, CurrentTime
);
388 /**************************************************************************
389 * GetClipboardOwner16 (USER.140)
391 HWND16 WINAPI
GetClipboardOwner16(void)
393 return hWndClipOwner
;
397 /**************************************************************************
398 * GetClipboardOwner32 (USER32.225)
400 HWND32 WINAPI
GetClipboardOwner32(void)
402 return hWndClipOwner
;
406 /**************************************************************************
407 * SetClipboardData16 (USER.141)
409 HANDLE16 WINAPI
SetClipboardData16( UINT16 wFormat
, HANDLE16 hData
)
411 LPCLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
414 TRACE(clipboard
, "(%04X, %04x) !\n", wFormat
, hData
);
416 /* NOTE: If the hData is zero and current owner doesn't match
417 * the window that opened the clipboard then this application
418 * is screwed because WM_RENDERFORMAT will go to the owner
419 * (to become the owner it must call EmptyClipboard() before
423 if( (hqClipLock
!= GetTaskQueue(0)) || !lpFormat
||
424 (!hData
&& (!hWndClipOwner
|| (hWndClipOwner
!= hWndClipWindow
))) ) return 0;
426 /* Acquire X selection if text format */
428 if( !selectionAcquired
&&
429 (wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
) )
431 owner
= WIN_GetXWindow( hWndClipWindow
? hWndClipWindow
: AnyPopup32() );
432 TSXSetSelectionOwner(display
,XA_PRIMARY
,owner
,CurrentTime
);
433 if( TSXGetSelectionOwner(display
,XA_PRIMARY
) == owner
)
435 selectionAcquired
= True
;
436 selectionWindow
= owner
;
438 TRACE(clipboard
,"Grabbed X selection, owner=(%08x)\n",
443 if ( lpFormat
->wDataPresent
|| lpFormat
->hData16
|| lpFormat
->hData32
)
445 CLIPBOARD_DeleteRecord(lpFormat
, TRUE
);
447 /* delete existing CF_TEXT/CF_OEMTEXT aliases */
449 if( wFormat
== CF_TEXT
450 && ( ClipFormats
[CF_OEMTEXT
-1].hData16
451 || ClipFormats
[CF_OEMTEXT
-1].hData32
)
452 && !ClipFormats
[CF_OEMTEXT
-1].wDataPresent
)
453 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
454 if( wFormat
== CF_OEMTEXT
455 && ( ClipFormats
[CF_OEMTEXT
-1].hData16
456 || ClipFormats
[CF_OEMTEXT
-1].hData32
)
457 && !ClipFormats
[CF_TEXT
-1].wDataPresent
)
458 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
461 bCBHasChanged
= TRUE
;
462 lpFormat
->wDataPresent
= 1;
463 lpFormat
->hData16
= hData
; /* 0 is legal, see WM_RENDERFORMAT */
464 lpFormat
->hData32
= 0;
466 return lpFormat
->hData16
;
470 /**************************************************************************
471 * SetClipboardData32 (USER32.470)
473 HANDLE32 WINAPI
SetClipboardData32( UINT32 wFormat
, HANDLE32 hData
)
475 LPCLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
478 TRACE(clipboard
, "(%08X, %08x) !\n", wFormat
, hData
);
480 /* NOTE: If the hData is zero and current owner doesn't match
481 * the window that opened the clipboard then this application
482 * is screwed because WM_RENDERFORMAT will go to the owner
483 * (to become the owner it must call EmptyClipboard() before
487 if( (hqClipLock
!= GetTaskQueue(0)) || !lpFormat
||
488 (!hData
&& (!hWndClipOwner
|| (hWndClipOwner
!= hWndClipWindow
))) ) return 0;
490 /* Acquire X selection if text format */
492 if( !selectionAcquired
&&
493 (wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
) )
495 owner
= WIN_GetXWindow( hWndClipWindow
? hWndClipWindow
: AnyPopup32() );
496 TSXSetSelectionOwner(display
,XA_PRIMARY
,owner
,CurrentTime
);
497 if( TSXGetSelectionOwner(display
,XA_PRIMARY
) == owner
)
499 selectionAcquired
= True
;
500 selectionWindow
= owner
;
502 TRACE(clipboard
,"Grabbed X selection, owner=(%08x)\n",
507 if ( lpFormat
->wDataPresent
|| lpFormat
->hData16
|| lpFormat
->hData32
)
509 CLIPBOARD_DeleteRecord(lpFormat
, TRUE
);
511 /* delete existing CF_TEXT/CF_OEMTEXT aliases */
513 if( wFormat
== CF_TEXT
514 && ( ClipFormats
[CF_OEMTEXT
-1].hData16
515 || ClipFormats
[CF_OEMTEXT
-1].hData32
)
516 && !ClipFormats
[CF_OEMTEXT
-1].wDataPresent
)
517 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_OEMTEXT
-1], TRUE
);
518 if( wFormat
== CF_OEMTEXT
519 && ( ClipFormats
[CF_OEMTEXT
-1].hData16
520 || ClipFormats
[CF_OEMTEXT
-1].hData32
)
521 && !ClipFormats
[CF_TEXT
-1].wDataPresent
)
522 CLIPBOARD_DeleteRecord(&ClipFormats
[CF_TEXT
-1], TRUE
);
525 bCBHasChanged
= TRUE
;
526 lpFormat
->wDataPresent
= 1;
527 lpFormat
->hData32
= hData
; /* 0 is legal, see WM_RENDERFORMAT */
528 lpFormat
->hData16
= 0;
530 return lpFormat
->hData32
;
534 /**************************************************************************
535 * CLIPBOARD_RenderFormat
537 static BOOL32
CLIPBOARD_RenderFormat(LPCLIPFORMAT lpFormat
)
539 if( lpFormat
->wDataPresent
&& !lpFormat
->hData16
&& !lpFormat
->hData32
)
541 if( IsWindow32(hWndClipOwner
) )
542 SendMessage16(hWndClipOwner
,WM_RENDERFORMAT
,
543 (WPARAM16
)lpFormat
->wFormatID
,0L);
546 WARN(clipboard
, "\thWndClipOwner (%04x) is lost!\n",
548 hWndClipOwner
= 0; lpFormat
->wDataPresent
= 0;
552 return (lpFormat
->hData16
|| lpFormat
->hData32
) ? TRUE
: FALSE
;
555 /**************************************************************************
556 * CLIPBOARD_RenderText
558 * Convert text between UNIX and DOS formats.
560 static BOOL32
CLIPBOARD_RenderText(LPCLIPFORMAT lpTarget
, LPCLIPFORMAT lpSource
)
566 if (lpSource
->hData32
)
568 size
= GlobalSize32( lpSource
->hData32
);
569 lpstrS
= (LPSTR
)GlobalLock32(lpSource
->hData32
);
573 size
= GlobalSize16( lpSource
->hData16
);
574 lpstrS
= (LPSTR
)GlobalLock16(lpSource
->hData16
);
577 if( !lpstrS
) return FALSE
;
578 TRACE(clipboard
,"\tconverting from '%s' to '%s', %i chars\n",
579 lpSource
->Name
, lpTarget
->Name
, size
);
581 lpTarget
->hData32
= GlobalAlloc32(GMEM_ZEROINIT
, size
);
582 lpstrT
= (LPSTR
)GlobalLock32(lpTarget
->hData32
);
586 if( lpSource
->wFormatID
== CF_TEXT
)
587 CharToOemBuff32A(lpstrS
, lpstrT
, size
);
589 OemToCharBuff32A(lpstrS
, lpstrT
, size
);
590 TRACE(clipboard
,"\tgot %s\n", lpstrT
);
591 GlobalUnlock32(lpTarget
->hData32
);
592 if (lpSource
->hData32
)
593 GlobalUnlock32(lpSource
->hData32
);
595 GlobalUnlock16(lpSource
->hData16
);
599 lpTarget
->hData32
= 0;
600 if (lpSource
->hData32
)
601 GlobalUnlock32(lpSource
->hData32
);
603 GlobalUnlock16(lpSource
->hData16
);
607 /**************************************************************************
608 * GetClipboardData16 (USER.142)
610 HANDLE16 WINAPI
GetClipboardData16( UINT16 wFormat
)
612 LPCLIPFORMAT lpRender
= ClipFormats
;
613 LPCLIPFORMAT lpUpdate
= NULL
;
615 if (hqClipLock
!= GetTaskQueue(0)) return 0;
617 TRACE(clipboard
,"(%04X)\n", wFormat
);
619 if( wFormat
== CF_TEXT
&& !lpRender
[CF_TEXT
-1].wDataPresent
620 && lpRender
[CF_OEMTEXT
-1].wDataPresent
)
622 lpRender
= &ClipFormats
[CF_OEMTEXT
-1];
623 lpUpdate
= &ClipFormats
[CF_TEXT
-1];
625 TRACE(clipboard
,"\tOEMTEXT -> TEXT\n");
627 else if( wFormat
== CF_OEMTEXT
&& !lpRender
[CF_OEMTEXT
-1].wDataPresent
628 && lpRender
[CF_TEXT
-1].wDataPresent
)
630 lpRender
= &ClipFormats
[CF_TEXT
-1];
631 lpUpdate
= &ClipFormats
[CF_OEMTEXT
-1];
633 TRACE(clipboard
,"\tTEXT -> OEMTEXT\n");
637 lpRender
= __lookup_format( ClipFormats
, wFormat
);
641 if( !lpRender
|| !CLIPBOARD_RenderFormat(lpRender
) ) return 0;
642 if( lpUpdate
!= lpRender
&& !lpUpdate
->hData16
&& !lpUpdate
->hData32
)
643 CLIPBOARD_RenderText(lpUpdate
, lpRender
);
645 if( lpUpdate
->hData32
&& !lpUpdate
->hData16
)
648 if( lpUpdate
->wFormatID
== CF_METAFILEPICT
)
649 size
= sizeof( METAFILEPICT16
);
651 size
= GlobalSize32(lpUpdate
->hData32
);
652 lpUpdate
->hData16
= GlobalAlloc16(GMEM_ZEROINIT
, size
);
653 if( !lpUpdate
->hData16
)
654 ERR(clipboard
, "(%04X) -- not enough memory in 16b heap\n", wFormat
);
657 if( lpUpdate
->wFormatID
== CF_METAFILEPICT
)
659 FIXME(clipboard
,"\timplement function CopyMetaFilePict32to16\n");
660 FIXME(clipboard
,"\tin the appropriate file.\n");
661 #ifdef SOMEONE_IMPLEMENTED_ME
662 CopyMetaFilePict32to16( GlobalLock16(lpUpdate
->hData16
),
663 GlobalLock32(lpUpdate
->hData32
) );
668 memcpy( GlobalLock16(lpUpdate
->hData16
),
669 GlobalLock32(lpUpdate
->hData32
),
672 GlobalUnlock16(lpUpdate
->hData16
);
673 GlobalUnlock32(lpUpdate
->hData32
);
677 TRACE(clipboard
,"\treturning %04x (type %i)\n",
678 lpUpdate
->hData16
, lpUpdate
->wFormatID
);
679 return lpUpdate
->hData16
;
683 /**************************************************************************
684 * GetClipboardData32 (USER32.222)
686 HANDLE32 WINAPI
GetClipboardData32( UINT32 wFormat
)
688 LPCLIPFORMAT lpRender
= ClipFormats
;
689 LPCLIPFORMAT lpUpdate
= NULL
;
691 if (hqClipLock
!= GetTaskQueue(0)) return 0;
693 TRACE(clipboard
,"(%08X)\n", wFormat
);
695 if( wFormat
== CF_TEXT
&& !lpRender
[CF_TEXT
-1].wDataPresent
696 && lpRender
[CF_OEMTEXT
-1].wDataPresent
)
698 lpRender
= &ClipFormats
[CF_OEMTEXT
-1];
699 lpUpdate
= &ClipFormats
[CF_TEXT
-1];
701 TRACE(clipboard
,"\tOEMTEXT -> TEXT\n");
703 else if( wFormat
== CF_OEMTEXT
&& !lpRender
[CF_OEMTEXT
-1].wDataPresent
704 && lpRender
[CF_TEXT
-1].wDataPresent
)
706 lpRender
= &ClipFormats
[CF_TEXT
-1];
707 lpUpdate
= &ClipFormats
[CF_OEMTEXT
-1];
709 TRACE(clipboard
,"\tTEXT -> OEMTEXT\n");
713 lpRender
= __lookup_format( ClipFormats
, wFormat
);
717 if( !lpRender
|| !CLIPBOARD_RenderFormat(lpRender
) ) return 0;
718 if( lpUpdate
!= lpRender
&& !lpUpdate
->hData16
&& !lpUpdate
->hData32
)
719 CLIPBOARD_RenderText(lpUpdate
, lpRender
);
721 if( lpUpdate
->hData16
&& !lpUpdate
->hData32
)
724 if( lpUpdate
->wFormatID
== CF_METAFILEPICT
)
725 size
= sizeof( METAFILEPICT32
);
727 size
= GlobalSize16(lpUpdate
->hData16
);
728 lpUpdate
->hData32
= GlobalAlloc32(GMEM_ZEROINIT
, size
);
729 if( lpUpdate
->wFormatID
== CF_METAFILEPICT
)
731 FIXME(clipboard
,"\timplement function CopyMetaFilePict16to32\n");
732 FIXME(clipboard
,"\tin the appropriate file.\n");
733 #ifdef SOMEONE_IMPLEMENTED_ME
734 CopyMetaFilePict16to32( GlobalLock16(lpUpdate
->hData32
),
735 GlobalLock32(lpUpdate
->hData16
) );
740 memcpy( GlobalLock32(lpUpdate
->hData32
),
741 GlobalLock16(lpUpdate
->hData16
),
744 GlobalUnlock32(lpUpdate
->hData32
);
745 GlobalUnlock16(lpUpdate
->hData16
);
748 TRACE(clipboard
,"\treturning %04x (type %i)\n",
749 lpUpdate
->hData32
, lpUpdate
->wFormatID
);
750 return lpUpdate
->hData32
;
753 /**************************************************************************
754 * CountClipboardFormats16 (USER.143)
756 INT16 WINAPI
CountClipboardFormats16(void)
758 return CountClipboardFormats32();
762 /**************************************************************************
763 * CountClipboardFormats32 (USER32.63)
765 INT32 WINAPI
CountClipboardFormats32(void)
767 INT32 FormatCount
= 0;
768 LPCLIPFORMAT lpFormat
= ClipFormats
;
770 TRACE(clipboard
,"(void)\n");
772 if( !selectionAcquired
) CLIPBOARD_RequestXSelection();
774 FormatCount
+= abs(lpFormat
[CF_TEXT
-1].wDataPresent
-
775 lpFormat
[CF_OEMTEXT
-1].wDataPresent
);
779 if (lpFormat
== NULL
) break;
780 if (lpFormat
->wDataPresent
)
782 TRACE(clipboard
, "\tdata found for format %i\n", lpFormat
->wFormatID
);
785 lpFormat
= lpFormat
->NextFormat
;
788 TRACE(clipboard
,"\ttotal %d\n", FormatCount
);
793 /**************************************************************************
794 * EnumClipboardFormats16 (USER.144)
796 UINT16 WINAPI
EnumClipboardFormats16( UINT16 wFormat
)
798 return EnumClipboardFormats32( wFormat
);
802 /**************************************************************************
803 * EnumClipboardFormats32 (USER32.179)
805 UINT32 WINAPI
EnumClipboardFormats32( UINT32 wFormat
)
807 LPCLIPFORMAT lpFormat
= ClipFormats
;
809 TRACE(clipboard
,"(%04X)\n", wFormat
);
811 if( hqClipLock
!= GetTaskQueue(0) ) return 0;
813 if( (!wFormat
|| wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
)
814 && !selectionAcquired
) CLIPBOARD_RequestXSelection();
818 if (lpFormat
->wDataPresent
|| ClipFormats
[CF_OEMTEXT
-1].wDataPresent
)
819 return lpFormat
->wFormatID
;
821 wFormat
= lpFormat
->wFormatID
; /* and CF_TEXT is not available */
824 /* walk up to the specified format record */
826 if( !(lpFormat
= __lookup_format( lpFormat
, wFormat
)) ) return 0;
828 /* find next format with available data */
830 lpFormat
= lpFormat
->NextFormat
;
833 if (lpFormat
== NULL
) return 0;
834 if (lpFormat
->wDataPresent
|| (lpFormat
->wFormatID
== CF_OEMTEXT
&&
835 ClipFormats
[CF_TEXT
-1].wDataPresent
))
837 lpFormat
= lpFormat
->NextFormat
;
840 return lpFormat
->wFormatID
;
844 /**************************************************************************
845 * RegisterClipboardFormat16 (USER.145)
847 UINT16 WINAPI
RegisterClipboardFormat16( LPCSTR FormatName
)
849 LPCLIPFORMAT lpNewFormat
;
850 LPCLIPFORMAT lpFormat
= ClipFormats
;
852 if (FormatName
== NULL
) return 0;
854 TRACE(clipboard
,"('%s') !\n", FormatName
);
856 /* walk format chain to see if it's already registered */
860 if ( !strcmp(lpFormat
->Name
,FormatName
) )
862 lpFormat
->wRefCount
++;
863 return lpFormat
->wFormatID
;
866 if ( lpFormat
->NextFormat
== NULL
) break;
868 lpFormat
= lpFormat
->NextFormat
;
871 /* allocate storage for new format entry */
873 lpNewFormat
= (LPCLIPFORMAT
)xmalloc(sizeof(CLIPFORMAT
));
874 lpFormat
->NextFormat
= lpNewFormat
;
875 lpNewFormat
->wFormatID
= LastRegFormat
;
876 lpNewFormat
->wRefCount
= 1;
878 lpNewFormat
->Name
= (LPSTR
)xmalloc(strlen(FormatName
) + 1);
879 strcpy(lpNewFormat
->Name
, FormatName
);
881 lpNewFormat
->wDataPresent
= 0;
882 lpNewFormat
->hData16
= 0;
883 lpNewFormat
->hData32
= 0;
884 lpNewFormat
->BufSize
= 0;
885 lpNewFormat
->PrevFormat
= lpFormat
;
886 lpNewFormat
->NextFormat
= NULL
;
888 return LastRegFormat
++;
892 /**************************************************************************
893 * RegisterClipboardFormat32A (USER32.431)
895 UINT32 WINAPI
RegisterClipboardFormat32A( LPCSTR formatName
)
897 return RegisterClipboardFormat16( formatName
);
901 /**************************************************************************
902 * RegisterClipboardFormat32W (USER32.432)
904 UINT32 WINAPI
RegisterClipboardFormat32W( LPCWSTR formatName
)
906 LPSTR aFormat
= HEAP_strdupWtoA( GetProcessHeap(), 0, formatName
);
907 UINT32 ret
= RegisterClipboardFormat32A( aFormat
);
908 HeapFree( GetProcessHeap(), 0, aFormat
);
912 /**************************************************************************
913 * GetClipboardFormatName16 (USER.146)
915 INT16 WINAPI
GetClipboardFormatName16( UINT16 wFormat
, LPSTR retStr
, INT16 maxlen
)
917 return GetClipboardFormatName32A( wFormat
, retStr
, maxlen
);
921 /**************************************************************************
922 * GetClipboardFormatName32A (USER32.223)
924 INT32 WINAPI
GetClipboardFormatName32A( UINT32 wFormat
, LPSTR retStr
, INT32 maxlen
)
926 LPCLIPFORMAT lpFormat
= __lookup_format( ClipFormats
, wFormat
);
928 TRACE(clipboard
, "(%04X, %p, %d) !\n", wFormat
, retStr
, maxlen
);
930 if (lpFormat
== NULL
|| lpFormat
->Name
== NULL
||
931 lpFormat
->wFormatID
< CF_REGFORMATBASE
) return 0;
933 TRACE(clipboard
, "Name='%s' !\n", lpFormat
->Name
);
935 lstrcpyn32A( retStr
, lpFormat
->Name
, maxlen
);
936 return strlen(retStr
);
940 /**************************************************************************
941 * GetClipboardFormatName32W (USER32.224)
943 INT32 WINAPI
GetClipboardFormatName32W( UINT32 wFormat
, LPWSTR retStr
, INT32 maxlen
)
945 LPSTR p
= HEAP_xalloc( GetProcessHeap(), 0, maxlen
);
946 INT32 ret
= GetClipboardFormatName32A( wFormat
, p
, maxlen
);
947 lstrcpynAtoW( retStr
, p
, maxlen
);
948 HeapFree( GetProcessHeap(), 0, p
);
953 /**************************************************************************
954 * SetClipboardViewer16 (USER.147)
956 HWND16 WINAPI
SetClipboardViewer16( HWND16 hWnd
)
958 return SetClipboardViewer32( hWnd
);
962 /**************************************************************************
963 * SetClipboardViewer32 (USER32.471)
965 HWND32 WINAPI
SetClipboardViewer32( HWND32 hWnd
)
967 HWND32 hwndPrev
= hWndViewer
;
969 TRACE(clipboard
,"(%04x): returning %04x\n", hWnd
, hwndPrev
);
976 /**************************************************************************
977 * GetClipboardViewer16 (USER.148)
979 HWND16 WINAPI
GetClipboardViewer16(void)
985 /**************************************************************************
986 * GetClipboardViewer32 (USER32.226)
988 HWND32 WINAPI
GetClipboardViewer32(void)
994 /**************************************************************************
995 * ChangeClipboardChain16 (USER.149)
997 BOOL16 WINAPI
ChangeClipboardChain16(HWND16 hWnd
, HWND16 hWndNext
)
999 return ChangeClipboardChain32(hWnd
, hWndNext
);
1002 /**************************************************************************
1003 * ChangeClipboardChain32 (USER32.22)
1005 BOOL32 WINAPI
ChangeClipboardChain32(HWND32 hWnd
, HWND32 hWndNext
)
1009 FIXME(clipboard
, "(0x%04x, 0x%04x): stub?\n", hWnd
, hWndNext
);
1012 bRet
= !SendMessage16( hWndViewer
, WM_CHANGECBCHAIN
,
1013 (WPARAM16
)hWnd
, (LPARAM
)hWndNext
);
1015 WARN(clipboard
, "hWndViewer is lost\n");
1017 if( hWnd
== hWndViewer
) hWndViewer
= hWndNext
;
1024 /**************************************************************************
1025 * IsClipboardFormatAvailable16 (USER.193)
1027 BOOL16 WINAPI
IsClipboardFormatAvailable16( UINT16 wFormat
)
1029 return IsClipboardFormatAvailable32( wFormat
);
1033 /**************************************************************************
1034 * IsClipboardFormatAvailable32 (USER32.340)
1036 BOOL32 WINAPI
IsClipboardFormatAvailable32( UINT32 wFormat
)
1038 TRACE(clipboard
,"(%04X) !\n", wFormat
);
1040 if( (wFormat
== CF_TEXT
|| wFormat
== CF_OEMTEXT
) &&
1041 !selectionAcquired
) CLIPBOARD_RequestXSelection();
1043 return CLIPBOARD_IsPresent(wFormat
);
1047 /**************************************************************************
1048 * GetOpenClipboardWindow16 (USER.248)
1050 HWND16 WINAPI
GetOpenClipboardWindow16(void)
1052 return hWndClipWindow
;
1056 /**************************************************************************
1057 * GetOpenClipboardWindow32 (USER32.277)
1059 HWND32 WINAPI
GetOpenClipboardWindow32(void)
1061 return hWndClipWindow
;
1065 /**************************************************************************
1066 * GetPriorityClipboardFormat16 (USER.402)
1068 INT16 WINAPI
GetPriorityClipboardFormat16( UINT16
*lpPriorityList
, INT16 nCount
)
1070 FIXME(clipboard
, "(%p,%d): stub\n", lpPriorityList
, nCount
);
1075 /**************************************************************************
1076 * GetPriorityClipboardFormat32 (USER32.279)
1078 INT32 WINAPI
GetPriorityClipboardFormat32( UINT32
*lpPriorityList
, INT32 nCount
)
1082 if(CountClipboardFormats32() == 0)
1087 for(Counter
= 0; Counter
<= nCount
; Counter
++)
1089 if(IsClipboardFormatAvailable32(*(lpPriorityList
+sizeof(INT32
)*Counter
)))
1090 return *(lpPriorityList
+sizeof(INT32
)*Counter
);
1097 /**************************************************************************
1098 * CLIPBOARD_ReadSelection
1100 * Called from the SelectionNotify event handler.
1102 void CLIPBOARD_ReadSelection(Window w
,Atom prop
)
1105 LPCLIPFORMAT lpFormat
= ClipFormats
;
1107 TRACE(clipboard
,"ReadSelection callback\n");
1111 Atom atype
=AnyPropertyType
;
1113 unsigned long nitems
,remain
;
1114 unsigned char* val
=NULL
;
1116 TRACE(clipboard
,"\tgot property %s\n",TSXGetAtomName(display
,prop
));
1118 /* TODO: Properties longer than 64K */
1120 if(TSXGetWindowProperty(display
,w
,prop
,0,0x3FFF,True
,XA_STRING
,
1121 &atype
, &aformat
, &nitems
, &remain
, &val
) != Success
)
1122 WARN(clipboard
, "\tcouldn't read property\n");
1125 TRACE(clipboard
,"\tType %s,Format %d,nitems %ld,value %s\n",
1126 TSXGetAtomName(display
,atype
),aformat
,nitems
,val
);
1128 if(atype
== XA_STRING
&& aformat
== 8)
1133 TRACE(clipboard
,"\tselection is '%s'\n",val
);
1135 for(i
=0; i
<= nitems
; i
++)
1136 if( val
[i
] == '\n' ) inlcount
++;
1140 hText
=GlobalAlloc32(GMEM_MOVEABLE
, nitems
+ inlcount
+ 1);
1141 if( (lpstr
= (char*)GlobalLock32(hText
)) )
1142 for(i
=0,inlcount
=0; i
<= nitems
; i
++)
1144 if( val
[i
] == '\n' ) lpstr
[inlcount
++]='\r';
1145 lpstr
[inlcount
++]=val
[i
];
1154 /* delete previous CF_TEXT and CF_OEMTEXT data */
1158 lpFormat
= &ClipFormats
[CF_TEXT
-1];
1159 if (lpFormat
->wDataPresent
|| lpFormat
->hData16
|| lpFormat
->hData32
)
1160 CLIPBOARD_DeleteRecord(lpFormat
, !(hWndClipWindow
));
1161 lpFormat
= &ClipFormats
[CF_OEMTEXT
-1];
1162 if (lpFormat
->wDataPresent
|| lpFormat
->hData16
|| lpFormat
->hData32
)
1163 CLIPBOARD_DeleteRecord(lpFormat
, !(hWndClipWindow
));
1165 lpFormat
->wDataPresent
= 1;
1166 lpFormat
->hData32
= hText
;
1167 lpFormat
->hData16
= 0;
1170 selectionWait
=False
;
1173 /**************************************************************************
1174 * CLIPBOARD_ReleaseSelection
1176 * Wine might have lost XA_PRIMARY selection because of
1177 * EmptyClipboard() or other client.
1179 void CLIPBOARD_ReleaseSelection(Window w
, HWND32 hwnd
)
1181 /* w is the window that lost selection,
1183 * selectionPrevWindow is nonzero if CheckSelection() was called.
1186 TRACE(clipboard
,"\tevent->window = %08x (sw = %08x, spw=%08x)\n",
1187 (unsigned)w
, (unsigned)selectionWindow
, (unsigned)selectionPrevWindow
);
1189 if( selectionAcquired
)
1191 if( w
== selectionWindow
|| selectionPrevWindow
== None
)
1193 /* alright, we really lost it */
1195 selectionAcquired
= False
;
1196 selectionWindow
= None
;
1198 /* but we'll keep existing data for internal use */
1200 else if( w
== selectionPrevWindow
)
1202 w
= TSXGetSelectionOwner(display
, XA_PRIMARY
);
1204 TSXSetSelectionOwner(display
, XA_PRIMARY
, selectionWindow
, CurrentTime
);
1208 selectionPrevWindow
= None
;