Added missing GDI heap unlock.
[wine/gsoc_dplay.git] / windows / x11drv / clipboard.c
blobcb07e66dfa7b60e213a26637e2a2c3e51d1e23ee
1 /*
2 * X11 windows driver
4 * Copyright 1994 Martin Ayotte
5 * 1996 Alex Korobka
6 */
8 #include "config.h"
10 #ifndef X_DISPLAY_MISSING
12 #include <X11/Xatom.h>
13 #include "ts_xlib.h"
15 #include "wine/winuser16.h"
16 #include "clipboard.h"
17 #include "debug.h"
18 #include "message.h"
19 #include "win.h"
20 #include "windef.h"
21 #include "x11drv.h"
23 DEFAULT_DEBUG_CHANNEL(clipboard)
25 extern HWND hWndClipOwner;
26 extern HWND hWndClipWindow;
27 extern WINE_CLIPFORMAT ClipFormats[];
29 static Bool selectionAcquired = False;
30 static Window selectionWindow = None;
31 static Window selectionPrevWindow = None;
33 /**************************************************************************
34 * X11DRV_CLIPBOARD_CheckSelection [Internal]
36 * Prevent X selection from being lost when a top level window is
37 * destroyed.
39 static void X11DRV_CLIPBOARD_CheckSelection(WND* pWnd)
41 TRACE(clipboard,"\tchecking %08x\n",
42 (unsigned) X11DRV_WND_GetXWindow(pWnd)
45 if( selectionAcquired && selectionWindow != None &&
46 X11DRV_WND_GetXWindow(pWnd) == selectionWindow )
48 selectionPrevWindow = selectionWindow;
49 selectionWindow = None;
51 if( pWnd->next )
52 selectionWindow = X11DRV_WND_GetXWindow(pWnd->next);
53 else if( pWnd->parent )
54 if( pWnd->parent->child != pWnd )
55 selectionWindow = X11DRV_WND_GetXWindow(pWnd->parent->child);
57 TRACE(clipboard,"\tswitching selection from %08x to %08x\n",
58 (unsigned)selectionPrevWindow, (unsigned)selectionWindow);
60 if( selectionWindow != None )
62 TSXSetSelectionOwner(display, XA_PRIMARY, selectionWindow, CurrentTime);
63 if( TSXGetSelectionOwner(display, XA_PRIMARY) != selectionWindow )
64 selectionWindow = None;
69 /**************************************************************************
70 * X11DRV_CLIPBOARD_ReadSelection
72 static void X11DRV_CLIPBOARD_ReadSelection(Window w, Atom prop)
74 HANDLE hText = 0;
75 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
77 TRACE(clipboard,"Reading X selection...\n");
79 if(prop != None)
81 Atom atype=AnyPropertyType;
82 int aformat;
83 unsigned long nitems,remain;
84 unsigned char* val=NULL;
86 TRACE(clipboard,"\tgot property %s\n",TSXGetAtomName(display,prop));
88 /* TODO: Properties longer than 64K */
90 if(TSXGetWindowProperty(display,w,prop,0,0x3FFF,True,XA_STRING,
91 &atype, &aformat, &nitems, &remain, &val) != Success)
92 WARN(clipboard, "\tcouldn't read property\n");
93 else
95 TRACE(clipboard,"\tType %s,Format %d,nitems %ld,value %s\n",
96 TSXGetAtomName(display,atype),aformat,nitems,val);
98 if(atype == XA_STRING && aformat == 8)
100 int i,inlcount = 0;
101 char* lpstr;
103 TRACE(clipboard,"\tselection is '%s'\n",val);
105 for(i=0; i <= nitems; i++)
106 if( val[i] == '\n' ) inlcount++;
108 if( nitems )
110 hText=GlobalAlloc(GMEM_MOVEABLE, nitems + inlcount + 1);
111 if( (lpstr = (char*)GlobalLock(hText)) )
112 for(i=0,inlcount=0; i <= nitems; i++)
114 if( val[i] == '\n' ) lpstr[inlcount++]='\r';
115 lpstr[inlcount++]=val[i];
117 else hText = 0;
120 TSXFree(val);
124 /* delete previous CF_TEXT and CF_OEMTEXT data */
126 if( hText )
128 lpFormat = &ClipFormats[CF_TEXT-1];
129 if (lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32)
130 CLIPBOARD_DeleteRecord(lpFormat, !(hWndClipWindow));
131 lpFormat = &ClipFormats[CF_OEMTEXT-1];
132 if (lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32)
133 CLIPBOARD_DeleteRecord(lpFormat, !(hWndClipWindow));
134 lpFormat->wDataPresent = 1;
135 lpFormat->hData32 = hText;
136 lpFormat->hData16 = 0;
140 /**************************************************************************
141 * X11DRV_CLIPBOARD_ReleaseSelection
143 * Wine might have lost XA_PRIMARY selection because of
144 * EmptyClipboard() or other client.
146 void X11DRV_CLIPBOARD_ReleaseSelection(Window w, HWND hwnd)
148 /* w is the window that lost selection,
150 * selectionPrevWindow is nonzero if CheckSelection() was called.
153 TRACE(clipboard,"\tevent->window = %08x (sw = %08x, spw=%08x)\n",
154 (unsigned)w, (unsigned)selectionWindow, (unsigned)selectionPrevWindow );
156 if( selectionAcquired )
158 if( w == selectionWindow || selectionPrevWindow == None)
160 /* alright, we really lost it */
162 selectionAcquired = False;
163 selectionWindow = None;
165 /* but we'll keep existing data for internal use */
167 else if( w == selectionPrevWindow )
169 w = TSXGetSelectionOwner(display, XA_PRIMARY);
170 if( w == None )
171 TSXSetSelectionOwner(display, XA_PRIMARY, selectionWindow, CurrentTime);
175 selectionPrevWindow = None;
178 /**************************************************************************
179 * X11DRV_CLIPBOARD_Empty
181 void X11DRV_CLIPBOARD_Empty()
183 if( selectionAcquired )
185 XEvent xe;
187 selectionAcquired = False;
188 selectionPrevWindow = selectionWindow;
189 selectionWindow = None;
191 TRACE(clipboard, "\tgiving up selection (spw = %08x)\n",
192 (unsigned)selectionPrevWindow);
194 EnterCriticalSection(&X11DRV_CritSection);
195 XSetSelectionOwner(display, XA_PRIMARY, None, CurrentTime);
197 if( selectionPrevWindow )
198 while( !XCheckTypedWindowEvent( display, selectionPrevWindow,
199 SelectionClear, &xe ) );
200 LeaveCriticalSection(&X11DRV_CritSection);
204 /**************************************************************************
205 * X11DRV_CLIPBOARD_SetData
207 void X11DRV_CLIPBOARD_SetData(UINT wFormat)
209 Window owner;
211 /* Acquire X selection if text format */
213 if( !selectionAcquired &&
214 (wFormat == CF_TEXT || wFormat == CF_OEMTEXT) )
216 WND *tmpWnd = WIN_FindWndPtr( hWndClipWindow ? hWndClipWindow : AnyPopup() );
217 owner = X11DRV_WND_FindXWindow(tmpWnd );
219 TSXSetSelectionOwner(display,XA_PRIMARY, owner, CurrentTime);
220 if( TSXGetSelectionOwner(display,XA_PRIMARY) == owner )
222 selectionAcquired = True;
223 selectionWindow = owner;
225 TRACE(clipboard,"Grabbed X selection, owner=(%08x)\n",
226 (unsigned) owner);
228 WIN_ReleaseWndPtr(tmpWnd);
232 /**************************************************************************
233 * X11DRV_CLIPBOARD_GetData
235 * NOTE: Clipboard driver doesn't get requests for CF_TEXT data, only
236 * for CF_OEMTEXT.
238 BOOL X11DRV_CLIPBOARD_GetData(UINT wFormat)
240 BOOL bRet = selectionAcquired;
241 HWND hWnd = (hWndClipWindow) ? hWndClipWindow : GetActiveWindow();
242 WND* wnd = NULL;
244 if( wFormat != CF_OEMTEXT ) return FALSE;
246 if( !bRet && (wnd = WIN_FindWndPtr(hWnd)) )
248 XEvent xe;
249 Window w = X11DRV_WND_FindXWindow(wnd);
251 TRACE(clipboard, "Requesting XA_STRING selection...\n");
253 EnterCriticalSection( &X11DRV_CritSection );
254 XConvertSelection(display, XA_PRIMARY, XA_STRING,
255 XInternAtom(display, "PRIMARY_TEXT", False),
256 w, CurrentTime);
258 /* wait until SelectionNotify is received */
260 while( TRUE )
262 if( XCheckTypedWindowEvent(display, w, SelectionNotify, &xe) )
263 if( xe.xselection.selection == XA_PRIMARY )
264 break;
266 LeaveCriticalSection( &X11DRV_CritSection );
268 if (xe.xselection.target != XA_STRING)
269 X11DRV_CLIPBOARD_ReadSelection( 0, None );
270 else
271 X11DRV_CLIPBOARD_ReadSelection( xe.xselection.requestor,
272 xe.xselection.property );
274 /* treat Unix text as CF_OEMTEXT */
276 bRet = (BOOL)ClipFormats[CF_OEMTEXT-1].wDataPresent;
278 TRACE(clipboard,"\tpresent CF_OEMTEXT = %i\n", bRet );
279 WIN_ReleaseWndPtr(wnd);
281 return bRet;
284 /**************************************************************************
285 * X11DRV_CLIPBOARD_ResetOwner
287 * Called from DestroyWindow().
289 void X11DRV_CLIPBOARD_ResetOwner(WND *pWnd, BOOL bFooBar)
291 LPWINE_CLIPFORMAT lpFormat = ClipFormats;
293 if(bFooBar && X11DRV_WND_GetXWindow(pWnd))
294 return;
296 if(!bFooBar && !X11DRV_WND_GetXWindow(pWnd))
297 return;
299 TRACE(clipboard,"clipboard owner = %04x, selection = %08x\n",
300 hWndClipOwner, (unsigned)selectionWindow);
302 if( pWnd->hwndSelf == hWndClipOwner)
304 SendMessage16(hWndClipOwner,WM_RENDERALLFORMATS,0,0L);
306 /* check if all formats were rendered */
308 while(lpFormat)
310 if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 )
312 TRACE(clipboard,"\tdata missing for clipboard format %i\n",
313 lpFormat->wFormatID);
314 lpFormat->wDataPresent = 0;
316 lpFormat = lpFormat->NextFormat;
318 hWndClipOwner = 0;
321 /* now try to salvage current selection from being destroyed by X */
323 if( X11DRV_WND_GetXWindow(pWnd) ) X11DRV_CLIPBOARD_CheckSelection(pWnd);
326 #endif /* !defined(X_DISPLAY_MISSING) */