2 * 'Wine' Clipboard function handling
4 * Copyright 1994 Martin Ayotte
7 static char Copyright
[] = "Copyright Martin Ayotte, 1994";
12 #include <sys/types.h>
17 #include <X11/Xatom.h>
18 #include "prototypes.h"
22 /* #define DEBUG_CLIPBOARD /* */
23 /* #undef DEBUG_CLIPBOARD /* */
26 typedef struct tagCLIPFORMAT
{
35 typedef CLIPFORMAT FAR
* LPCLIPFORMAT
;
37 static HWND hWndClipboardOwner
= 0;
38 static HWND hWndViewer
= 0;
39 static WORD LastRegFormat
= 0xC000;
40 static Bool wait_for_selection
= False
;
41 static Bool wineOwnsSelection
= False
;
43 CLIPFORMAT ClipFormats
[12] = {
44 { CF_TEXT
, 1, "Text", (HANDLE
)NULL
, 0, NULL
, &ClipFormats
[1] },
45 { CF_BITMAP
, 1, "Bitmap", (HANDLE
)NULL
, 0, &ClipFormats
[0], &ClipFormats
[2] },
46 { CF_METAFILEPICT
, 1, "MetaFile Picture", (HANDLE
)NULL
, 0, &ClipFormats
[1], &ClipFormats
[3] },
47 { CF_SYLK
, 1, "Sylk", (HANDLE
)NULL
, 0, &ClipFormats
[2], &ClipFormats
[4] },
48 { CF_DIF
, 1, "DIF", (HANDLE
)NULL
, 0, &ClipFormats
[3], &ClipFormats
[5] },
49 { CF_TIFF
, 1, "TIFF", (HANDLE
)NULL
, 0, &ClipFormats
[4], &ClipFormats
[6] },
50 { CF_OEMTEXT
, 1, "OEM Text", (HANDLE
)NULL
, 0, &ClipFormats
[5], &ClipFormats
[7] },
51 { CF_DIB
, 1, "DIB", (HANDLE
)NULL
, 0, &ClipFormats
[6], &ClipFormats
[8] },
52 { CF_PALETTE
, 1, "Palette", (HANDLE
)NULL
, 0, &ClipFormats
[7], &ClipFormats
[9] },
53 { CF_PENDATA
, 1, "PenData", (HANDLE
)NULL
, 0, &ClipFormats
[8], &ClipFormats
[10] },
54 { CF_RIFF
, 1, "RIFF", (HANDLE
)NULL
, 0, &ClipFormats
[9], &ClipFormats
[11] },
55 { CF_WAVE
, 1, "Wave", (HANDLE
)NULL
, 0, &ClipFormats
[10], NULL
}
58 /**************************************************************************
59 * OpenClipboard [USER.137]
61 BOOL
OpenClipboard(HWND hWnd
)
63 if (hWndClipboardOwner
!= 0) return FALSE
;
64 hWndClipboardOwner
= hWnd
;
65 dprintf_clipboard(stddeb
,"OpenClipboard(%04X); !\n", hWnd
);
70 /**************************************************************************
71 * CloseClipboard [USER.138]
75 if (hWndClipboardOwner
== 0) return FALSE
;
76 hWndClipboardOwner
= 0;
77 dprintf_clipboard(stddeb
,"CloseClipboard(); !\n");
82 /**************************************************************************
83 * EmptyClipboard [USER.139]
87 LPCLIPFORMAT lpFormat
= ClipFormats
;
88 if (hWndClipboardOwner
== 0) return FALSE
;
89 dprintf_clipboard(stddeb
,"EmptyClipboard(); !\n");
91 if (lpFormat
== NULL
) break;
92 if (lpFormat
->hData
!= 0) {
93 GlobalFree(lpFormat
->hData
);
96 lpFormat
= lpFormat
->NextFormat
;
98 if(wineOwnsSelection
){
99 dprintf_clipboard(stddeb
,"Losing selection\n");
100 wineOwnsSelection
=False
;
101 XSetSelectionOwner(display
,XA_PRIMARY
,None
,CurrentTime
);
107 /**************************************************************************
108 * GetClipboardOwner [USER.140]
110 HWND
GetClipboardOwner()
112 dprintf_clipboard(stddeb
,
113 "GetClipboardOwner() = %04X !\n", hWndClipboardOwner
);
114 return hWndClipboardOwner
;
118 /**************************************************************************
119 * SetClipboardData [USER.141]
121 HANDLE
SetClipboardData(WORD wFormat
, HANDLE hData
)
123 LPCLIPFORMAT lpFormat
= ClipFormats
;
124 dprintf_clipboard(stddeb
,
125 "SetClipboardDate(%04X, %04X) !\n", wFormat
, hData
);
127 if (lpFormat
== NULL
) return 0;
128 if (lpFormat
->wFormatID
== wFormat
) break;
129 lpFormat
= lpFormat
->NextFormat
;
131 /* doc says we shouldn't use CurrentTime */
132 /* should we become owner of CLIPBOARD as well? */
133 XSetSelectionOwner(display
,XA_PRIMARY
,WIN_GetXWindow(hWndClipboardOwner
),CurrentTime
);
134 wineOwnsSelection
= True
;
135 dprintf_clipboard(stddeb
,"Getting selection\n");
136 if (lpFormat
->hData
!= 0) GlobalFree(lpFormat
->hData
);
137 lpFormat
->hData
= hData
;
138 return lpFormat
->hData
;
142 /**************************************************************************
143 * GetClipboardData [USER.142]
145 HANDLE
GetClipboardData(WORD wFormat
)
147 LPCLIPFORMAT lpFormat
= ClipFormats
;
148 dprintf_clipboard(stddeb
,"GetClipboardData(%04X) !\n", wFormat
);
149 if(wFormat
== CF_TEXT
&& !wineOwnsSelection
)
150 { wait_for_selection
=True
;
151 dprintf_clipboard(stddeb
,"Requesting selection\n");
152 XConvertSelection(display
,XA_PRIMARY
,XA_STRING
,
153 XInternAtom(display
,"PRIMARY_TEXT",False
),
154 WIN_GetXWindow(hWndClipboardOwner
),CurrentTime
);
155 /* TODO: need time-out for broken clients */
156 while(wait_for_selection
)MSG_WaitXEvent(-1);
159 if (lpFormat
== NULL
) return 0;
160 if (lpFormat
->wFormatID
== wFormat
) break;
161 lpFormat
= lpFormat
->NextFormat
;
163 return lpFormat
->hData
;
167 /**************************************************************************
168 * CountClipboardFormats [USER.143]
170 int CountClipboardFormats()
173 LPCLIPFORMAT lpFormat
= ClipFormats
;
175 if (lpFormat
== NULL
) break;
176 if (lpFormat
->hData
!= 0) {
177 dprintf_clipboard(stddeb
,
178 "CountClipboardFormats // Find Not Empty (%04X) !\n",
182 lpFormat
= lpFormat
->NextFormat
;
184 dprintf_clipboard(stddeb
,"CountClipboardFormats() = %d !\n", FormatCount
);
189 /**************************************************************************
190 * EnumClipboardFormats [USER.144]
192 WORD
EnumClipboardFormats(WORD wFormat
)
194 LPCLIPFORMAT lpFormat
= ClipFormats
;
195 dprintf_clipboard(stddeb
,"EnumClipboardFormats(%04X) !\n", wFormat
);
197 if (lpFormat
->hData
!= 0)
198 return lpFormat
->wFormatID
;
200 wFormat
= lpFormat
->wFormatID
;
203 if (lpFormat
== NULL
) return 0;
204 if (lpFormat
->wFormatID
== wFormat
) break;
205 lpFormat
= lpFormat
->NextFormat
;
207 dprintf_clipboard(stddeb
,"EnumClipboardFormats // Find Last (%04X) !\n",
208 lpFormat
->wFormatID
);
209 lpFormat
= lpFormat
->NextFormat
;
211 if (lpFormat
== NULL
) return 0;
212 if (lpFormat
->hData
!= 0) break;
213 lpFormat
= lpFormat
->NextFormat
;
215 dprintf_clipboard(stddeb
,
216 "EnumClipboardFormats // Find Not Empty Id=%04X hData=%04X !\n",
217 lpFormat
->wFormatID
, lpFormat
->hData
);
218 return lpFormat
->wFormatID
;
222 /**************************************************************************
223 * RegisterClipboardFormat [USER.145]
225 WORD
RegisterClipboardFormat(LPCSTR FormatName
)
227 LPCLIPFORMAT lpNewFormat
;
228 LPCLIPFORMAT lpFormat
= ClipFormats
;
229 if (FormatName
== NULL
) return 0;
231 if (lpFormat
->NextFormat
== NULL
) break;
232 lpFormat
= lpFormat
->NextFormat
;
234 lpNewFormat
= (LPCLIPFORMAT
)malloc(sizeof(CLIPFORMAT
));
235 if (lpNewFormat
== NULL
) return 0;
236 lpFormat
->NextFormat
= lpNewFormat
;
237 dprintf_clipboard(stddeb
,"RegisterClipboardFormat('%s') !\n", FormatName
);
238 lpNewFormat
->wFormatID
= LastRegFormat
;
239 lpNewFormat
->wRefCount
= 1;
240 lpNewFormat
->Name
= (LPSTR
)malloc(strlen(FormatName
) + 1);
241 if (lpNewFormat
->Name
== NULL
) {
245 strcpy(lpNewFormat
->Name
, FormatName
);
246 lpNewFormat
->hData
= 0;
247 lpNewFormat
->BufSize
= 0;
248 lpNewFormat
->PrevFormat
= lpFormat
;
249 lpNewFormat
->NextFormat
= NULL
;
250 return LastRegFormat
++;
254 /**************************************************************************
255 * GetClipboardFormatName [USER.146]
257 int GetClipboardFormatName(WORD wFormat
, LPSTR retStr
, short maxlen
)
259 LPCLIPFORMAT lpFormat
= ClipFormats
;
260 dprintf_clipboard(stddeb
,
261 "GetClipboardFormat(%04X, %p, %d) !\n", wFormat
, retStr
, maxlen
);
263 if (lpFormat
== NULL
) return 0;
264 if (lpFormat
->wFormatID
== wFormat
) break;
265 lpFormat
= lpFormat
->NextFormat
;
267 if (lpFormat
->Name
== NULL
) return 0;
268 dprintf_clipboard(stddeb
,
269 "GetClipboardFormat // Name='%s' !\n", lpFormat
->Name
);
270 maxlen
= min(maxlen
- 1, strlen(lpFormat
->Name
));
271 dprintf_clipboard(stddeb
,"GetClipboardFormat // maxlen=%d !\n", maxlen
);
272 memcpy(retStr
, lpFormat
->Name
, maxlen
);
278 /**************************************************************************
279 * SetClipboardViewer [USER.147]
281 HWND
SetClipboardViewer(HWND hWnd
)
283 HWND hwndPrev
= hWndViewer
;
284 dprintf_clipboard(stddeb
,"SetClipboardViewer(%04X) !\n", hWnd
);
290 /**************************************************************************
291 * GetClipboardViewer [USER.148]
293 HWND
GetClipboardViewer()
295 dprintf_clipboard(stddeb
,"GetClipboardFormat() = %04X !\n", hWndViewer
);
300 /**************************************************************************
301 * ChangeClipboardChain [USER.149]
303 BOOL
ChangeClipboardChain(HWND hWnd
, HWND hWndNext
)
305 dprintf_clipboard(stdnimp
,
306 "ChangeClipboardChain(%04X, %04X) !\n", hWnd
, hWndNext
);
310 /**************************************************************************
311 * IsClipboardFormatAvailable [USER.193]
313 BOOL
IsClipboardFormatAvailable(WORD wFormat
)
315 LPCLIPFORMAT lpFormat
= ClipFormats
;
316 dprintf_clipboard(stddeb
,"IsClipboardFormatAvailable(%04X) !\n", wFormat
);
317 if(wFormat
== CF_TEXT
&& !wineOwnsSelection
) /* obtain selection as text if possible */
318 return GetClipboardData(CF_TEXT
)!=0;
320 if (lpFormat
== NULL
) return FALSE
;
321 if (lpFormat
->wFormatID
== wFormat
) break;
322 lpFormat
= lpFormat
->NextFormat
;
324 return (lpFormat
->hData
!= 0);
328 /**************************************************************************
329 * GetOpenClipboardWindow [USER.248]
331 HWND
GetOpenClipboardWindow()
333 dprintf_clipboard(stddeb
,
334 "GetOpenClipboardWindow() = %04X !\n", hWndClipboardOwner
);
335 return hWndClipboardOwner
;
339 /**************************************************************************
340 * GetPriorityClipboardFormat [USER.402]
342 int GetPriorityClipboardFormat(WORD FAR
*lpPriorityList
, short nCount
)
344 dprintf_clipboard(stdnimp
,
345 "GetPriorityClipboardFormat(%p, %d) !\n", lpPriorityList
, nCount
);
349 /**************************************************************************
350 * CLIPBOARD_ReadSelection
352 * The current selection owner has set prop at our window w
353 * Transfer the property contents into the Clipboard
355 void CLIPBOARD_ReadSelection(Window w
,Atom prop
)
358 LPCLIPFORMAT lpFormat
= ClipFormats
;
364 unsigned long nitems
,remain
;
365 unsigned char *val
=NULL
;
366 dprintf_clipboard(stddeb
,"Received prop %s\n",XGetAtomName(display
,prop
));
367 /* TODO: Properties longer than 64K */
368 if(XGetWindowProperty(display
,w
,prop
,0,0x3FFF,True
,XA_STRING
,
369 &atype
, &aformat
, &nitems
, &remain
, &val
)!=Success
)
370 printf("couldn't read property\n");
371 dprintf_clipboard(stddeb
,"Type %s,Format %d,nitems %ld,value %s\n",
372 XGetAtomName(display
,atype
),aformat
,nitems
,val
);
373 if(atype
!=XA_STRING
|| aformat
!=8){
374 fprintf(stderr
,"Property not set\n");
377 dprintf_clipboard(stddeb
,"Selection is %s\n",val
);
378 hText
=GlobalAlloc(GMEM_MOVEABLE
, nitems
);
379 memcpy(GlobalLock(hText
),val
,nitems
+1);
385 if (lpFormat
== NULL
) return;
386 if (lpFormat
->wFormatID
== CF_TEXT
) break;
387 lpFormat
= lpFormat
->NextFormat
;
389 if (lpFormat
->hData
!= 0) GlobalFree(lpFormat
->hData
);
390 wait_for_selection
=False
;
391 lpFormat
->hData
= hText
;
392 dprintf_clipboard(stddeb
,"Received selection\n");
395 /**************************************************************************
396 * CLIPBOARD_ReleaseSelection
398 * Wine lost the primary selection.
399 * Empty the clipboard, but don't set the current owner to None.
400 * Make sure current get/put attempts fail.
402 void CLIPBOARD_ReleaseSelection(HWND hwnd
)
404 wineOwnsSelection
=False
;